brintos

brintos / llvm-project-archived public Read only

0
0
Text · 35.2 KiB · 43e1f6b Raw
1143 lines · cpp
1// RUN: %clang_cc1            -verify=expected,both                        -fexperimental-new-constant-interpreter %s2// RUN: %clang_cc1 -std=c++20 -verify=expected,both                        -fexperimental-new-constant-interpreter %s3// RUN: %clang_cc1 -std=c++20 -verify=expected,both -triple=i686-linux-gnu -fexperimental-new-constant-interpreter %s4// RUN: %clang_cc1            -verify=ref,both                                                                     %s5// RUN: %clang_cc1 -std=c++20 -verify=ref,both                                                                     %s6// RUN: %clang_cc1 -std=c++20 -verify=ref,both      -triple=i686-linux-gnu                                         %s7 8#if __cplusplus >= 202002L9 10constexpr int *Global = new int(12); // both-error {{must be initialized by a constant expression}} \11                                     // both-note {{pointer to heap-allocated object}} \12                                     // both-note {{heap allocation performed here}}13 14static_assert(*(new int(12)) == 12); // both-error {{not an integral constant expression}} \15                                     // both-note {{allocation performed here was not deallocated}}16 17 18constexpr int a() {19  new int(12); // both-note {{allocation performed here was not deallocated}}20  return 1;21}22static_assert(a() == 1, ""); // both-error {{not an integral constant expression}}23 24constexpr int b() {25  int *i = new int(12);26  int m = *i;27  delete(i);28  return m;29}30static_assert(b() == 12, "");31 32 33struct S {34  int a;35  int b;36 37  static constexpr S *create(int a, int b) {38    return new S(a, b);39  }40};41 42constexpr int c() {43  S *s = new S(12, 13);44 45  int i = s->a;46  delete s;47 48  return i;49}50static_assert(c() == 12, "");51 52/// Dynamic allocation in function ::create(), freed in function d().53constexpr int d() {54  S* s = S::create(12, 14);55 56  int sum = s->a + s->b;57  delete s;58  return sum;59}60static_assert(d() == 26);61 62 63/// Test we emit the right diagnostic for several allocations done on64/// the same site.65constexpr int loop() {66  for (int i = 0; i < 10; ++i) {67    int *a = new int[10]; // both-note {{not deallocated (along with 9 other memory leaks)}}68  }69 70  return 1;71}72static_assert(loop() == 1, ""); // both-error {{not an integral constant expression}}73 74/// No initializer.75constexpr int noInit() {76  int *i = new int;77  delete i;78  return 0;79}80static_assert(noInit() == 0, "");81 82/// Try to delete a pointer that hasn't been heap allocated.83constexpr int notHeapAllocated() { // both-error {{never produces a constant expression}}84  int A = 0; // both-note 2{{declared here}}85  delete &A; // both-note 2{{delete of pointer '&A' that does not point to a heap-allocated object}}86 87  return 1;88}89static_assert(notHeapAllocated() == 1, ""); // both-error {{not an integral constant expression}} \90                                            // both-note {{in call to 'notHeapAllocated()'}}91 92consteval int deleteNull() {93  int *A = nullptr;94  delete A;95  return 1;96}97static_assert(deleteNull() == 1, "");98 99consteval int doubleDelete() { // both-error {{never produces a constant expression}}100  int *A = new int;101  delete A;102  delete A; // both-note 2{{delete of pointer that has already been deleted}}103  return 1;104}105static_assert(doubleDelete() == 1); // both-error {{not an integral constant expression}} \106                                    // both-note {{in call to 'doubleDelete()'}}107 108constexpr int AutoArray() {109  auto array = new int[]{0, 1, 2, 3};110  int ret = array[3];111  delete [] array;112  return ret;113}114 115static_assert(AutoArray() == 3);116 117#if 0118consteval int largeArray1(bool b) {119  if (b) {120    int *a = new int[1ull<<32]; // both-note {{cannot allocate array; evaluated array bound 4294967296 is too large}}121    delete[] a;122  }123  return 1;124}125static_assert(largeArray1(false) == 1, "");126static_assert(largeArray1(true) == 1, ""); // both-error {{not an integral constant expression}} \127                                           // both-note {{in call to 'largeArray1(true)'}}128 129consteval int largeArray2(bool b) {130  if (b) {131    S *a = new S[1ull<<32]; // both-note {{cannot allocate array; evaluated array bound 4294967296 is too large}}132    delete[] a;133  }134  return 1;135}136static_assert(largeArray2(false) == 1, "");137static_assert(largeArray2(true) == 1, ""); // both-error {{not an integral constant expression}} \138                                           // both-note {{in call to 'largeArray2(true)'}}139#endif140namespace Arrays {141  constexpr int d() {142    int *Arr = new int[12];143 144    Arr[0] = 1;145    Arr[1] = 5;146 147    int sum = Arr[0] + Arr[1];148    delete[] Arr;149    return sum;150  }151  static_assert(d() == 6);152 153 154  constexpr int mismatch1() { // both-error {{never produces a constant expression}}155    int *i = new int(12); // both-note {{allocated with 'new' here}} \156                          // both-note 2{{heap allocation performed here}}157    delete[] i; // both-warning {{'delete[]' applied to a pointer that was allocated with 'new'}} \158                // both-note 2{{array delete used to delete pointer to non-array object of type 'int'}}159    return 6;160  }161  static_assert(mismatch1() == 6); // both-error {{not an integral constant expression}} \162                                   // both-note {{in call to 'mismatch1()'}}163 164  constexpr int mismatch2() { // both-error {{never produces a constant expression}}165    int *i = new int[12]; // both-note {{allocated with 'new[]' here}} \166                          // both-note 2{{heap allocation performed here}}167    delete i; // both-warning {{'delete' applied to a pointer that was allocated with 'new[]'}} \168              // both-note 2{{non-array delete used to delete pointer to array object of type 'int[12]'}}169    return 6;170  }171  static_assert(mismatch2() == 6); // both-error {{not an integral constant expression}} \172                                   // both-note {{in call to 'mismatch2()'}}173 174  constexpr int mismatch3() { // both-error {{never produces a constant expression}}175    int a = 0;176    struct S {};177    struct T : S {};178    T *p = new T[3]{}; // both-note 2{{heap allocation performed here}}179    delete (S*)p; // both-note 2{{non-array delete used to delete pointer to array object of type 'T[3]'}}180 181    return 0;182 183  }184  static_assert(mismatch3() == 0); // both-error {{not an integral constant expression}} \185                                   // both-note {{in call to}}186 187  /// Array of composite elements.188  constexpr int foo() {189    S *ss = new S[12];190 191    ss[0].a = 12;192 193    int m = ss[0].a;194 195    delete[] ss;196    return m;197  }198  static_assert(foo() == 12);199 200 201 202  constexpr int ArrayInit() {203    auto array = new int[4]{0, 1, 2, 3};204    int ret = array[0];205    delete [] array;206    return ret;207  }208  static_assert(ArrayInit() == 0, "");209 210  struct S {211    float F;212  };213  constexpr float ArrayInit2() {214    auto array = new S[4]{};215    float ret = array[0].F;216    delete [] array;217    return ret;218  }219  static_assert(ArrayInit2() == 0.0f, "");220}221 222namespace std {223  struct type_info;224  struct destroying_delete_t {225    explicit destroying_delete_t() = default;226  } inline constexpr destroying_delete{};227  struct nothrow_t {228    explicit nothrow_t() = default;229  } inline constexpr nothrow{};230  using size_t = decltype(sizeof(0));231  enum class align_val_t : size_t {};232};233 234[[nodiscard]] void *operator new(std::size_t, const std::nothrow_t&) noexcept;235[[nodiscard]] void *operator new(std::size_t, std::align_val_t, const std::nothrow_t&) noexcept;236[[nodiscard]] void *operator new[](std::size_t, const std::nothrow_t&) noexcept;237[[nodiscard]] void *operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) noexcept;238[[nodiscard]] void *operator new[](std::size_t, std::align_val_t);239void operator delete(void*, const std::nothrow_t&) noexcept;240void operator delete(void*, std::align_val_t, const std::nothrow_t&) noexcept;241void operator delete[](void*, const std::nothrow_t&) noexcept;242void operator delete[](void*, std::align_val_t, const std::nothrow_t&) noexcept;243 244struct placement_new_arg {};245void *operator new(std::size_t, placement_new_arg);246void operator delete(void*, placement_new_arg);247 248 249constexpr void *operator new(std::size_t, void *p) { return p; }250namespace std {251  template<typename T> constexpr T *construct(T *p) { return new (p) T; }252  template<typename T> constexpr void destroy(T *p) { p->~T(); }253}254 255 256 257namespace PlacementNew {258  constexpr int foo() { // both-error {{never produces a constant expression}}259    char c[sizeof(int)];260    new (c) int{12}; // both-note {{this placement new expression is not supported in constant expressions before C++2c}}261    return 0;262  }263}264 265namespace NowThrowNew {266  constexpr bool erroneous_array_bound_nothrow(long long n) {267    int *p = new (std::nothrow) int[n];268    bool result = p != nullptr;269    delete[] p;270    return result;271  }272  static_assert(erroneous_array_bound_nothrow(3));273  static_assert(erroneous_array_bound_nothrow(0));274  static_assert(erroneous_array_bound_nothrow(-1) == 0);275  static_assert(!erroneous_array_bound_nothrow(1LL << 62));276 277  struct S { int a; };278  constexpr bool erroneous_array_bound_nothrow2(long long n) {279    S *p = new (std::nothrow) S[n];280    bool result = p != nullptr;281    delete[] p;282    return result;283  }284  static_assert(erroneous_array_bound_nothrow2(3));285  static_assert(erroneous_array_bound_nothrow2(0));286  static_assert(erroneous_array_bound_nothrow2(-1) == 0);287  static_assert(!erroneous_array_bound_nothrow2(1LL << 62));288 289  constexpr bool erroneous_array_bound(long long n) {290    delete[] new int[n]; // both-note {{array bound -1 is negative}} both-note {{array bound 4611686018427387904 is too large}}291    return true;292  }293  static_assert(erroneous_array_bound(3));294  static_assert(erroneous_array_bound(0));295  static_assert(erroneous_array_bound(-1)); // both-error {{constant expression}} both-note {{in call}}296  static_assert(erroneous_array_bound(1LL << 62)); // both-error {{constant expression}} both-note {{in call}}297 298  constexpr bool evaluate_nothrow_arg() {299    bool ok = false;300    delete new ((ok = true, std::nothrow)) int;301    return ok;302  }303  static_assert(evaluate_nothrow_arg());304}305 306namespace placement_new_delete {307  struct ClassSpecificNew {308    void *operator new(std::size_t);309  };310  struct ClassSpecificDelete {311    void operator delete(void*);312  };313  struct DestroyingDelete {314    void operator delete(DestroyingDelete*, std::destroying_delete_t);315  };316  struct alignas(64) Overaligned {};317 318  constexpr bool ok() {319    delete new Overaligned;320    delete ::new ClassSpecificNew;321    ::delete new ClassSpecificDelete;322    ::delete new DestroyingDelete;323    return true;324  }325  static_assert(ok());326 327  constexpr bool bad(int which) {328    switch (which) {329    case 0:330      delete new (placement_new_arg{}) int; // both-note {{this placement new expression is not supported in constant expressions}}331      break;332 333    case 1:334      delete new ClassSpecificNew; // both-note {{call to class-specific 'operator new'}}335      break;336 337    case 2:338      delete new ClassSpecificDelete; // both-note {{call to class-specific 'operator delete'}}339      break;340 341    case 3:342      delete new DestroyingDelete; // both-note {{call to class-specific 'operator delete'}}343      break;344 345    case 4:346      // FIXME: This technically follows the standard's rules, but it seems347      // unreasonable to expect implementations to support this.348      delete new (std::align_val_t{64}) Overaligned; // both-note {{this placement new expression is not supported in constant expressions}}349      break;350    }351 352    return true;353  }354  static_assert(bad(0)); // both-error {{constant expression}} \355                         // both-note {{in call}}356  static_assert(bad(1)); // both-error {{constant expression}} both-note {{in call}}357  static_assert(bad(2)); // both-error {{constant expression}} both-note {{in call}}358  static_assert(bad(3)); // both-error {{constant expression}} both-note {{in call}}359  static_assert(bad(4)); // both-error {{constant expression}} \360                         // both-note {{in call}}361}362 363 364 365 366namespace delete_random_things {367  static_assert((delete new int, true));368  static_assert((delete (int*)0, true));369  int n; // both-note {{declared here}}370  static_assert((delete &n, true)); // both-error {{}} \371                                    // both-note {{delete of pointer '&n' that does not point to a heap-allocated object}}372  struct A { int n; };373  static_assert((delete &(new A)->n, true)); // both-error {{}} \374                                             // both-note {{delete of pointer to subobject }}375  static_assert((delete (new int + 1), true)); // both-error {{}} \376                                               // both-note {{delete of pointer '&{*new int#0} + 1' that does not point to complete object}}377  static_assert((delete[] (new int[3] + 1), true)); // both-error {{}} \378                                                    // both-note {{delete of pointer to subobject}}379  static_assert((delete &(int&)(int&&)0, true)); // both-error {{}} \380                                                 // both-note {{delete of pointer '&0' that does not point to a heap-allocated object}} \381                                                 // both-note {{temporary created here}}382}383 384namespace value_dependent_delete {385  template<typename T> void f(T *p) {386    int arr[(delete p, 0)];387  }388}389 390namespace memory_leaks {391  static_assert(*new bool(true)); // both-error {{}} both-note {{allocation performed here was not deallocated}}392 393  constexpr bool *f() { return new bool(true); } // both-note {{allocation performed here was not deallocated}}394  static_assert(*f()); // both-error {{}}395 396  struct UP {397    bool *p;398    constexpr ~UP() { delete p; }399    constexpr bool &operator*() { return *p; }400  };401  constexpr UP g() { return {new bool(true)}; }402  static_assert(*g()); // ok403 404  constexpr bool h(UP p) { return *p; }405  static_assert(h({new bool(true)})); // ok406}407 408/// From test/SemaCXX/cxx2a-consteval.cpp409 410namespace std {411template <typename T> struct remove_reference { using type = T; };412template <typename T> struct remove_reference<T &> { using type = T; };413template <typename T> struct remove_reference<T &&> { using type = T; };414template <typename T>415constexpr typename std::remove_reference<T>::type&& move(T &&t) noexcept {416  return static_cast<typename std::remove_reference<T>::type &&>(t);417}418}419 420namespace cxx2a {421struct A {422  int* p = new int(42); // both-note 3{{heap allocation performed here}}423  consteval int ret_i() const { return p ? *p : 0; }424  consteval A ret_a() const { return A{}; }425  constexpr ~A() { delete p; }426};427 428consteval int by_value_a(A a) { return a.ret_i(); }429 430consteval int const_a_ref(const A &a) {431  return a.ret_i();432}433 434consteval int rvalue_ref(const A &&a) {435  return a.ret_i();436}437 438consteval const A &to_lvalue_ref(const A &&a) {439  return a;440}441 442void test() {443  constexpr A a{ nullptr };444  { int k = A().ret_i(); }445 446  { A k = A().ret_a(); } // both-error {{'cxx2a::A::ret_a' is not a constant expression}} \447                         // both-note {{heap-allocated object is not a constant expression}}448  { A k = to_lvalue_ref(A()); } // both-error {{'cxx2a::to_lvalue_ref' is not a constant expression}} \449                                // both-note {{reference to temporary is not a constant expression}} \450                                // both-note {{temporary created here}}451  { A k = to_lvalue_ref(A().ret_a()); } // both-error {{'cxx2a::to_lvalue_ref' is not a constant expression}} \452                                        // both-note {{reference to temporary is not a constant expression}} \453                                        // both-note {{temporary created here}}454  { int k = A().ret_a().ret_i(); } // both-error {{'cxx2a::A::ret_a' is not a constant expression}} \455                                   // both-note {{heap-allocated object is not a constant expression}}456  { int k = by_value_a(A()); }457  { int k = const_a_ref(A()); }458  { int k = const_a_ref(a); }459  { int k = rvalue_ref(A()); }460  { int k = rvalue_ref(std::move(a)); }461  { int k = const_a_ref(A().ret_a()); }462  { int k = const_a_ref(to_lvalue_ref(A().ret_a())); }463  { int k = const_a_ref(to_lvalue_ref(std::move(a))); }464  { int k = by_value_a(A().ret_a()); }465  { int k = by_value_a(to_lvalue_ref(static_cast<const A&&>(a))); }466  { int k = (A().ret_a(), A().ret_i()); } // both-error {{'cxx2a::A::ret_a' is not a constant expression}} \467                                          // both-note {{is not a constant expression}} \468                                          // both-warning {{left operand of comma operator has no effect}}469  { int k = (const_a_ref(A().ret_a()), A().ret_i()); } // both-warning {{left operand of comma operator has no effect}}470}471}472 473constexpr int *const &p = new int; // both-error {{must be initialized by a constant expression}} \474                                   // both-note {{pointer to heap-allocated object}} \475                                   // both-note {{allocation performed here}}476 477constexpr const int *A[] = {nullptr, nullptr, new int{12}}; // both-error {{must be initialized by a constant expression}} \478                                                            // both-note {{pointer to heap-allocated object}} \479                                                            // both-note {{allocation performed here}}480 481struct Sp {482  const int *p;483};484constexpr Sp ss[] = {Sp{new int{154}}}; // both-error {{must be initialized by a constant expression}} \485                                        // both-note {{pointer to heap-allocated object}} \486                                        // both-note {{allocation performed here}}487 488namespace DeleteRunsDtors {489  struct InnerFoo {490    int *mem;491    constexpr ~InnerFoo() {492      delete mem;493    }494  };495 496  struct Foo {497    int *a;498    InnerFoo IF;499 500    constexpr Foo() {501      a = new int(13);502      IF.mem = new int(100);503    }504    constexpr ~Foo() { delete a; }505  };506 507  constexpr int abc() {508    Foo *F = new Foo();509    int n = *F->a;510    delete F;511 512    return n;513  }514  static_assert(abc() == 13);515 516  constexpr int abc2() {517    Foo *f = new Foo[3];518 519    delete[] f;520 521    return 1;522  }523  static_assert(abc2() == 1);524}525 526/// FIXME: There is a slight difference in diagnostics here.527namespace FaultyDtorCalledByDelete {528  struct InnerFoo {529    int *mem;530    constexpr ~InnerFoo() {531      if (mem) {532        (void)(1/0); // both-warning {{division by zero is undefined}} \533                     // both-note {{division by zero}}534      }535      delete mem;536    }537  };538 539  struct Foo {540    int *a;541    InnerFoo IF;542 543    constexpr Foo() {544      a = new int(13);545      IF.mem = new int(100);546    }547    constexpr ~Foo() { delete a; }548  };549 550  constexpr int abc() {551    Foo *F = new Foo();552    int n = *F->a;553    delete F; // both-note 2{{in call to}}554 555    return n;556  }557  static_assert(abc() == 13); // both-error {{not an integral constant expression}} \558                              // both-note {{in call to 'abc()'}}559}560 561namespace DeleteThis {562  constexpr bool super_secret_double_delete() {563    struct A {564      constexpr ~A() { delete this; } // both-note {{destruction of object that is already being destroyed}} \565                                      // ref-note {{in call to}}566    };567    delete new A; // both-note {{in call to}}568    return true;569  }570  static_assert(super_secret_double_delete()); // both-error {{not an integral constant expression}} \571                                               // both-note {{in call to 'super_secret_double_delete()'}}572 573  struct B {574    constexpr void reset() { delete this; }575  };576  static_assert(((new B)->reset(), true));577}578 579namespace CastedDelete {580  struct S {581    constexpr S(int *p) : p(p) {}582    constexpr virtual ~S() { *p = 1; }583    int *p;584  };585  struct T: S {586    // implicit destructor defined eagerly because it is constexpr and virtual587    using S::S;588  };589 590  constexpr int vdtor_1() {591    int a;592    delete (S*)new T(&a);593    return a;594  }595  static_assert(vdtor_1() == 1);596 597  constexpr int foo() { // both-error {{never produces a constant expression}}598      struct S {};599      struct T : S {};600      S *p = new T();601      delete p; // both-note 2{{delete of object with dynamic type 'T' through pointer to base class type 'S' with non-virtual destructor}}602      return 1;603  }604  static_assert(foo() == 1); // both-error {{not an integral constant expression}} \605                             // both-note {{in call to}}606}607 608constexpr void use_after_free_2() { // both-error {{never produces a constant expression}}609  struct X { constexpr void f() {} };610  X *p = new X;611  delete p;612  p->f(); // both-note {{member call on heap allocated object that has been deleted}}613}614 615/// std::allocator definition616namespace std {617  using size_t = decltype(sizeof(0));618  template<typename T> struct allocator {619    constexpr T *allocate(size_t N) {620      return (T*)__builtin_operator_new(sizeof(T) * N); // #alloc621    }622    constexpr void deallocate(void *p) {623      __builtin_operator_delete(p); // both-note 2{{std::allocator<...>::deallocate' used to delete pointer to object allocated with 'new'}} \624                                    // both-note {{used to delete a null pointer}} \625                                    // both-note {{delete of pointer '&no_deallocate_nonalloc' that does not point to a heap-allocated object}}626    }627  };628  template<typename T, typename ...Args>629  constexpr void construct_at(void *p, Args &&...args) { // #construct630    new (p) T((Args&&)args...);631  }632}633 634constexpr int *escape = std::allocator<int>().allocate(3); // both-error {{constant expression}} \635                                                           // both-note {{pointer to subobject of heap-allocated}} \636                                                           // both-note {{heap allocation performed here}}637 638/// Specialization for float, using operator new/delete.639namespace std {640  using size_t = decltype(sizeof(0));641  template<> struct allocator<float> {642    constexpr float *allocate(size_t N) {643      return (float*)operator new (sizeof(float) * N);644    }645    constexpr void deallocate(void *p) {646      operator delete(p);647    }648  };649}650 651namespace OperatorNewDelete {652 653  constexpr bool mismatched(int alloc_kind, int dealloc_kind) {654    int *p;655    switch (alloc_kind) {656    case 0:657      p = new int; // both-note {{heap allocation performed here}}658      break;659    case 1:660      p = new int[1]; // both-note {{heap allocation performed here}}661      break;662    case 2:663      p = std::allocator<int>().allocate(1); // both-note 2{{heap allocation performed here}}664      break;665    }666    switch (dealloc_kind) {667    case 0:668      delete p; // both-note {{'delete' used to delete pointer to object allocated with 'std::allocator<...>::allocate'}}669      break;670    case 1:671      delete[] p; // both-note {{'delete' used to delete pointer to object allocated with 'std::allocator<...>::allocate'}}672      break;673    case 2:674      std::allocator<int>().deallocate(p); // both-note 2{{in call}}675      break;676    }677    return true;678  }679  static_assert(mismatched(0, 2)); // both-error {{constant expression}} \680                                   // both-note {{in call to}}681  static_assert(mismatched(1, 2)); // both-error {{constant expression}} \682                                   // both-note {{in call to}}683  static_assert(mismatched(2, 0)); // both-error {{constant expression}} \684                                   // both-note {{in call}}685  static_assert(mismatched(2, 1)); // both-error {{constant expression}} \686                                   // both-note {{in call}}687  static_assert(mismatched(2, 2));688 689  constexpr bool zeroAlloc() {690    int *F = std::allocator<int>().allocate(0);691    std::allocator<int>().deallocate(F);692    return true;693  }694  static_assert(zeroAlloc());695 696  constexpr int arrayAlloc() {697    int *F = std::allocator<int>().allocate(2);698    F[0] = 10; // both-note {{assignment to object outside its lifetime is not allowed in a constant expression}}699    F[1] = 13;700    int Res = F[1] + F[0];701    std::allocator<int>().deallocate(F);702    return Res;703  }704  static_assert(arrayAlloc() == 23); // both-error {{not an integral constant expression}} \705                                     // both-note {{in call to}}706 707  struct S {708    int i;709    constexpr S(int i) : i(i) {}710    constexpr ~S() { }711  };712 713  /// FIXME: This is broken in the current interpreter.714  constexpr bool structAlloc() {715    S *s = std::allocator<S>().allocate(1);716 717    s->i = 12; // ref-note {{assignment to object outside its lifetime is not allowed in a constant expression}}718 719    bool Res = (s->i == 12);720    std::allocator<S>().deallocate(s);721 722    return Res;723  }724  static_assert(structAlloc()); // ref-error {{not an integral constant expression}} \725                                // ref-note {{in call to}}726 727  constexpr bool structAllocArray() {728    S *s = std::allocator<S>().allocate(9);729 730    s[2].i = 12; // ref-note {{assignment to object outside its lifetime is not allowed in a constant expression}}731    bool Res = (s[2].i == 12);732    std::allocator<S>().deallocate(s);733 734    return Res;735  }736  static_assert(structAllocArray()); // ref-error {{not an integral constant expression}} \737                                     // ref-note {{in call to}}738 739  constexpr bool alloc_from_user_code() {740    void *p = __builtin_operator_new(sizeof(int)); // both-note {{cannot allocate untyped memory in a constant expression; use 'std::allocator<T>::allocate'}}741    __builtin_operator_delete(p);742    return true;743  }744  static_assert(alloc_from_user_code()); // both-error {{constant expression}} \745                                         // both-note {{in call to}}746 747 748  constexpr int no_deallocate_nullptr = (std::allocator<int>().deallocate(nullptr), 1); // both-error {{constant expression}} \749                                                                                        // both-note {{in call}}750 751  static_assert((std::allocator<float>().deallocate(std::allocator<float>().allocate(10)), 1) == 1);752}753 754namespace Limits {755  template<typename T>756  constexpr T dynarray(int elems, int i) {757    T *p;758    if constexpr (sizeof(T) == 1)759      p = new T[elems]{"fox"};760    else761      p = new T[elems]{1, 2, 3};762    T n = p[i];763    delete [] p;764    return n;765  }766  static_assert(dynarray<char>(5, 0) == 'f');767 768 769#if __LP64__770  template <typename T>771  struct S {772      constexpr S(unsigned long long N)773      : data(nullptr){774          data = alloc.allocate(N); // both-note {{in call to 'this->alloc.allocate(18446744073709551615)}}775      }776      constexpr T operator[](std::size_t i) const {777        return data[i];778      }779 780      constexpr ~S() {781          alloc.deallocate(data);782      }783      std::allocator<T> alloc;784      T* data;785  };786 787  constexpr std::size_t s = S<std::size_t>(~0UL)[42]; // both-error {{constexpr variable 's' must be initialized by a constant expression}} \788                                                      // both-note@#alloc {{cannot allocate array; evaluated array bound 2305843009213693951 is too large}} \789                                                      // both-note {{in call to}}790#endif791}792 793/// Just test that we reject placement-new expressions before C++2c.794/// Tests for successful expressions are in placement-new.cpp795namespace Placement {796  consteval auto ok1() { // both-error {{never produces a constant expression}}797    bool b;798    new (&b) bool(true); // both-note 2{{this placement new expression is not supported in constant expressions before C++2c}}799    return b;800  }801  static_assert(ok1()); // both-error {{not an integral constant expression}} \802                        // both-note {{in call to}}803 804  /// placement-new should be supported before C++26 in std functions.805  constexpr int ok2() {806    int *I = new int;807    std::construct_at<int>(I);808    int r = *I;809    delete I;810    return r;811  }812  static_assert(ok2()== 0);813}814 815constexpr bool virt_delete(bool global) {816  struct A {817    virtual constexpr ~A() {}818  };819  struct B : A {820    void operator delete(void *);821    constexpr ~B() {}822  };823 824  A *p = new B;825  if (global)826    ::delete p;827  else828    delete p; // both-note {{call to class-specific 'operator delete'}}829  return true;830}831static_assert(virt_delete(true));832static_assert(virt_delete(false)); // both-error {{not an integral constant expression}} \833                                   // both-note {{in call to}}834 835 836namespace ToplevelScopeInTemplateArg {837  class string {838  public:839    char *mem;840    constexpr string() {841      this->mem = new char(1);842    }843    constexpr ~string() {844      delete this->mem;845    }846    constexpr unsigned size() const { return 4; }847  };848 849 850  template <unsigned N>851  void test() {};852 853  void f() {854      test<string().size()>();855      static_assert(string().size() == 4);856  }857}858 859template <typename T>860struct SS {861    constexpr SS(unsigned long long N)862    : data(nullptr){863        data = alloc.allocate(N);864        for(std::size_t i = 0; i < N; i ++)865            std::construct_at<T>(data + i, i);866    }867 868    constexpr SS()869    : data(nullptr){870        data = alloc.allocate(1);871        std::construct_at<T>(data);872    }873 874    constexpr T operator[](std::size_t i) const {875      return data[i];876    }877 878    constexpr ~SS() {879        alloc.deallocate(data);880    }881    std::allocator<T> alloc;882    T* data;883};884constexpr unsigned short ssmall = SS<unsigned short>(100)[42];885constexpr auto Ss = SS<S>()[0];886 887 888namespace IncompleteArray {889  struct A {890    int b = 10;891  };892  constexpr int test1() {893    int n = 5;894    int* a = new int[n];895    int c = a[0]; // both-note {{read of uninitialized object}}896    delete[] a;897    return c;898  }899  static_assert(test1() == 10); // both-error {{not an integral constant expression}} \900                                // both-note {{in call to}}901 902  constexpr int test2() {903    int n = 0;904    int* a = new int[n];905    delete[] a;906    return 10;907  }908  static_assert(test2() == 10);909 910  /// In this case, the type of the initializer is A[2], while the full size of the911  /// allocated array is of course 5. The remaining 3 elements need to be initialized912  /// using A's constructor.913  constexpr int test3() {914    int n = 3;915    A* a = new A[n]{5, 1};916    int c = a[0].b + a[1].b + a[2].b;917    delete[] a;918    return c;919  }920  static_assert(test3() == (5 + 1 + 10));921 922  constexpr int test4() {923    auto n = 3;924    int *a = new int[n]{12};925    int c =  a[0] + a[1];926    delete[] a;927    return c;928  }929  static_assert(test4() == 12);930 931 932  constexpr char *f(int n) {933    return new char[n]();934  }935  static_assert((delete[] f(2), true));936}937 938namespace NonConstexprArrayCtor {939  struct S {940    S() {} // both-note 2{{declared here}}941  };942 943  constexpr bool test() { // both-error {{never produces a constant expression}}944     auto s = new S[1]; // both-note 2{{non-constexpr constructor}}945     return true;946  }947  static_assert(test()); // both-error {{not an integral constant expression}} \948                         // both-note {{in call to}}949}950 951namespace ArrayBaseCast {952  struct A {};953  struct B : A {};954  constexpr bool test() {955    B *b = new B[2];956 957    A* a = b;958 959    delete[] b;960    return true;961  }962  static_assert(test());963}964 965namespace PR45350 {966  int q;967  struct V { int n; int *p = &n; constexpr ~V() { *p = *p * 10 + n; }};968  constexpr int f(int n) {969    int k = 0;970    V *p = new V[n];971    for (int i = 0; i != n; ++i) {972      if (p[i].p != &p[i].n) return -1;973      p[i].n = i;974      p[i].p = &k;975    }976    delete[] p;977    return k;978  }979  // [expr.delete]p6:980  //   In the case of an array, the elements will be destroyed in order of981  //   decreasing address982  static_assert(f(6) == 543210);983}984 985namespace ZeroSizeSub {986  consteval unsigned ptr_diff1() {987    int *b = new int[0];988    unsigned d = 0;989    d = b - b;990    delete[] b;991 992    return d;993  }994  static_assert(ptr_diff1() == 0);995 996 997  consteval unsigned ptr_diff2() { // both-error {{never produces a constant expression}}998    int *a = new int[0];999    int *b = new int[0];1000 1001    unsigned d = a - b; // both-note 2{{arithmetic involving unrelated objects}}1002    delete[] b;1003    delete[] a;1004    return d;1005  }1006  static_assert(ptr_diff2() == 0); // both-error {{not an integral constant expression}} \1007                                   // both-note {{in call to}}1008}1009 1010namespace WrongFrame {1011  constexpr int foo() {1012    int *p = nullptr;1013    __builtin_operator_delete(p); // both-note {{subexpression not valid in a constant expression}}1014 1015    return 1;1016  }1017  static_assert(foo()); // both-error {{not an integral constant expression}} \1018                        // both-note {{in call to}}1019 1020}1021 1022constexpr int no_deallocate_nonalloc = (std::allocator<int>().deallocate((int*)&no_deallocate_nonalloc), 1); // both-error {{constant expression}} \1023                                                                                                             // both-note {{in call}} \1024                                                                                                             // both-note {{declared here}}1025 1026namespace OpNewNothrow {1027  constexpr int f() {1028      int *v = (int*)operator new(sizeof(int), std::align_val_t(2), std::nothrow); // both-note {{cannot allocate untyped memory in a constant expression; use 'std::allocator<T>::allocate' to allocate memory of type 'T'}}1029      operator delete(v, std::align_val_t(2), std::nothrow);1030      return 1;1031  }1032  static_assert(f()); // both-error {{not an integral constant expression}} \1033                      // both-note {{in call to}}1034}1035 1036namespace BaseCompare {1037  struct Cmp {1038    void *p;1039 1040    template<typename T>1041    constexpr Cmp(T *t) : p(t) {}1042 1043    constexpr friend bool operator==(Cmp a, Cmp b) {1044      return a.p == b.p;1045    }1046  };1047 1048  class Base {};1049  class Derived : public Base {};1050  constexpr bool foo() {1051    Derived *D = std::allocator<Derived>{}.allocate(1);;1052    std::construct_at<Derived>(D);1053 1054    Derived *d = D;1055    Base    *b = D;1056 1057    Cmp ca(d);1058    Cmp cb(b);1059 1060    if (ca == cb) {1061      std::allocator<Derived>{}.deallocate(D);1062      return true;1063    }1064    std::allocator<Derived>{}.deallocate(D);1065 1066    return false;1067 1068  }1069  static_assert(foo());1070}1071 1072 1073namespace NegativeArraySize { 1074  constexpr void f() { // both-error {{constexpr function never produces a constant expression}}1075    int x = -1;1076    int *p = new int[x]; //both-note {{cannot allocate array; evaluated array bound -1 is negative}} 1077  }1078} // namespace NegativeArraySize1079 1080namespace NewNegSizeNothrow {1081  constexpr int get_neg_size() {1082    return -1;1083  }1084 1085  constexpr bool test_nothrow_neg_size() {1086    int x = get_neg_size();1087    int* p = new (std::nothrow) int[x]; 1088    return p == nullptr;1089  }1090 1091  static_assert(test_nothrow_neg_size(), "expected nullptr");1092} // namespace NewNegSizeNothrow1093 1094#if __SIZEOF_SIZE_T == 81095/// We can't allocate the array here as it is too big.1096/// Make sure we're not crashing by assuming an non-null1097/// Descriptor.1098namespace HugeAllocation {1099  void *p;1100  void foo ()1101  {1102    p = new char [256][256][256][256][256];1103  }1104}1105#endif1106 1107namespace ZeroSizeArray {1108  constexpr int foo() {1109    int *A = new int[0];1110    int diff = A - (&A[0]);1111    delete[] A;1112    return diff;1113  }1114  static_assert(foo() == 0);1115}1116 1117namespace NonLiteralType {1118  /// This used to crash.1119  constexpr void foo() {1120    struct O {};1121 1122    struct S {1123      O *s;1124      constexpr S() : s{std::allocator<O>{}.allocate(1)} {}1125    };1126  }1127}1128 1129#else1130/// Make sure we reject this prior to C++201131constexpr int a() { // both-error {{never produces a constant expression}}1132  delete new int(12); // both-note 2{{dynamic memory allocation is not permitted in constant expressions until C++20}}1133  return 1;1134}1135static_assert(a() == 1, ""); // both-error {{not an integral constant expression}} \1136                             // both-note {{in call to 'a()'}}1137 1138 1139static_assert(true ? *new int : 4, ""); // both-error {{expression is not an integral constant expression}} \1140                                        // both-note {{read of uninitialized object is not allowed in a constant expression}}1141 1142#endif1143