brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.8 KiB · 25cd2c9 Raw
314 lines · cpp
1// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx20 %s -DNEW=__builtin_operator_new -DDELETE=__builtin_operator_delete2// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx20 %s "-DNEW=operator new" "-DDELETE=operator delete"3// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx20 %s "-DNEW=::operator new" "-DDELETE=::operator delete"4// RUN: %clang_cc1 -std=c++2c -verify=expected,cxx26 %s "-DNEW=::operator new" "-DDELETE=::operator delete"5 6// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx20 %s -DNEW=__builtin_operator_new -DDELETE=__builtin_operator_delete -fexperimental-new-constant-interpreter7// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx20 %s "-DNEW=operator new" "-DDELETE=operator delete" -fexperimental-new-constant-interpreter8// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx20 %s "-DNEW=::operator new" "-DDELETE=::operator delete" -fexperimental-new-constant-interpreter9// RUN: %clang_cc1 -std=c++2c -verify=expected,cxx26 %s "-DNEW=::operator new" "-DDELETE=::operator delete" -fexperimental-new-constant-interpreter10 11constexpr bool alloc_from_user_code() {12  void *p = NEW(sizeof(int)); // expected-note {{cannot allocate untyped memory in a constant expression; use 'std::allocator<T>::allocate'}}13  DELETE(p);14  return true;15}16static_assert(alloc_from_user_code()); // expected-error {{constant expression}} expected-note {{in call}}17 18namespace std {19  using size_t = decltype(sizeof(0));20  template<typename T> struct allocator {21    constexpr T *allocate(size_t N) {22      return (T*)NEW(sizeof(T) * N);23    }24    constexpr void deallocate(void *p) {25      DELETE(p); // #dealloc expected-note 2{{'std::allocator<...>::deallocate' used to delete pointer to object allocated with 'new'}}26    }27  };28}29 30constexpr bool alloc_via_std_allocator() {31  std::allocator<int> alloc;32  int *p = alloc.allocate(1);33  alloc.deallocate(p);34  return true;35}36static_assert(alloc_via_std_allocator());37 38template<> struct std::allocator<void()> {39  constexpr void *allocate() { return NEW(8); } // expected-note {{cannot allocate memory of function type 'void ()'}}40};41constexpr void *fn = std::allocator<void()>().allocate(); // expected-error {{constant expression}} expected-note {{in call}}42 43struct Incomplete;44template<> struct std::allocator<Incomplete> {45  constexpr void *allocate() { return NEW(8); } // expected-note {{cannot allocate memory of incomplete type 'Incomplete'}}46};47constexpr void *incomplete = std::allocator<Incomplete>().allocate(); // expected-error {{constant expression}} expected-note {{in call}}48 49struct WrongSize { char x[5]; };50static_assert(sizeof(WrongSize) == 5);51template<> struct std::allocator<WrongSize> {52  constexpr void *allocate() { return NEW(7); } // expected-note {{allocated size 7 is not a multiple of size 5 of element type 'WrongSize'}}53};54constexpr void *wrong_size = std::allocator<WrongSize>().allocate(); // expected-error {{constant expression}} expected-note {{in call}}55 56constexpr bool mismatched(int alloc_kind, int dealloc_kind) {57  int *p;58  switch (alloc_kind) {59  case 0:60    p = new int; // expected-note {{heap allocation}}61    break;62  case 1:63    p = new int[1]; // expected-note {{heap allocation}}64    break;65  case 2:66    p = std::allocator<int>().allocate(1); // expected-note 2{{heap allocation}}67    break;68  }69  switch (dealloc_kind) {70  case 0:71    delete p; // expected-note {{'delete' used to delete pointer to object allocated with 'std::allocator<...>::allocate'}}72    break;73  case 1:74    delete[] p; // expected-note {{'delete' used to delete pointer to object allocated with 'std::allocator<...>::allocate'}}75    break;76  case 2:77    std::allocator<int>().deallocate(p); // expected-note 2{{in call}}78    break;79  }80  return true;81}82static_assert(mismatched(0, 2)); // expected-error {{constant expression}} expected-note {{in call}}83static_assert(mismatched(1, 2)); // expected-error {{constant expression}} expected-note {{in call}}84static_assert(mismatched(2, 0)); // expected-error {{constant expression}} expected-note {{in call}}85static_assert(mismatched(2, 1)); // expected-error {{constant expression}} expected-note {{in call}}86static_assert(mismatched(2, 2));87 88constexpr int *escape = std::allocator<int>().allocate(3); // expected-error {{constant expression}} expected-note {{pointer to subobject of heap-allocated}} \89                                                           // expected-note {{heap allocation performed here}}90constexpr int leak = (std::allocator<int>().allocate(3), 0); // expected-error {{constant expression}} \91                                                             // expected-note {{not deallocated}}92constexpr int no_lifetime_start = (*std::allocator<int>().allocate(1) = 1); // expected-error {{constant expression}} expected-note {{assignment to object outside its lifetime}}93constexpr int no_deallocate_nullptr = (std::allocator<int>().deallocate(nullptr), 1); // expected-error {{constant expression}} expected-note {{in call}}94// expected-note@#dealloc {{'std::allocator<...>::deallocate' used to delete a null pointer}}95constexpr int no_deallocate_nonalloc = (std::allocator<int>().deallocate((int*)&no_deallocate_nonalloc), 1); // expected-error {{constant expression}} expected-note {{in call}}96// expected-note@#dealloc {{delete of pointer '&no_deallocate_nonalloc' that does not point to a heap-allocated object}}97// expected-note@-2 {{declared here}}98 99void *operator new(std::size_t, void *p) { return p; }100void* operator new[] (std::size_t, void* p) {return p;}101constexpr bool no_placement_new_in_user_code() { // cxx20-error {{constexpr function never produces a constant expression}}102  int a;103  new (&a) int(42); // cxx20-note {{this placement new expression is not supported in constant expressions before C++2c}}104  return a == 42;105}106 107namespace std {108  constexpr bool placement_new_in_stdlib() {109    int a;110    new (&a) int(42);111    return a == 42;112  }113}114static_assert(std::placement_new_in_stdlib());115 116namespace std {117  template<typename T, typename ...Args>118  constexpr void construct_at(void *p, Args &&...args) {119    new (p) T((Args&&)args...); // #new120  }121}122 123constexpr bool call_std_construct_at() {124  int *p = std::allocator<int>().allocate(3);125  std::construct_at<int>(p, 1);126  std::construct_at<int>(p + 1, 2);127  std::construct_at<int>(p + 2, 3);128  bool good = p[0] + p[1] + p[2] == 6;129  std::allocator<int>().deallocate(p);130  return good;131}132static_assert(call_std_construct_at());133 134constexpr bool bad_construct_at_type() {135  int a;136  // expected-note@#new {{placement new would change type of storage from 'int' to 'float'}}137  std::construct_at<float>(&a, 1.0f); // expected-note {{in call}}138  return true;139}140static_assert(bad_construct_at_type()); // expected-error{{}} expected-note {{in call}}141 142constexpr bool bad_construct_at_subobject() {143  struct X { int a, b; };144  union A {145    int a;146    X x;147  };148  A a = {1};149  // expected-note@#new {{construction of subobject of member 'x' of union with active member 'a' is not allowed in a constant expression}}150  std::construct_at<int>(&a.x.a, 1); // expected-note {{in call}}151  return true;152}153static_assert(bad_construct_at_subobject()); // expected-error{{}} expected-note {{in call}}154 155constexpr bool change_union_member() {156  union U {157    int a;158    int b;159  };160  U u = {.a = 1};161  std::construct_at<int>(&u.b, 2);162  return u.b == 2;163}164static_assert(change_union_member());165 166int external;167// expected-note@#new {{visible outside}}168static_assert((std::construct_at<int>(&external, 1), true)); // expected-error{{}} expected-note {{in call}}169 170constexpr int &&temporary = 0; // expected-note {{created here}}171// expected-note@#new {{construction of temporary is not allowed in a constant expression outside the expression that created the temporary}}172static_assert((std::construct_at<int>(&temporary, 1), true)); // expected-error{{}} expected-note {{in call}}173 174constexpr bool construct_after_lifetime() {175  int *p = new int;176  delete p;177  // expected-note@#new {{construction of heap allocated object that has been deleted}}178  std::construct_at<int>(p); // expected-note {{in call}}179  return true;180}181static_assert(construct_after_lifetime()); // expected-error {{}} expected-note {{in call}}182 183constexpr bool construct_after_lifetime_2() {184  struct A { struct B {} b; };185  A a;186  a.~A();187  std::construct_at<A::B>(&a.b); // expected-note {{in call}}188  // expected-note@#new {{construction of subobject of object outside its lifetime is not allowed in a constant expression}}189  return true;190}191static_assert(construct_after_lifetime_2()); // expected-error {{}} expected-note {{in call}}192 193namespace PR48606 {194  struct A { mutable int n = 0; };195 196  constexpr bool f() {197    A a;198    A *p = &a;199    p->~A();200    std::construct_at<A>(p);201    return true;202  }203  static_assert(f());204 205  constexpr bool g() {206    A *p = new A;207    p->~A();208    std::construct_at<A>(p);209    delete p;210    return true;211  }212  static_assert(g());213 214  constexpr bool h() {215    std::allocator<A> alloc;216    A *p = alloc.allocate(1);217    std::construct_at<A>(p);218    p->~A();219    std::construct_at<A>(p);220    p->~A();221    alloc.deallocate(p);222    return true;223  }224  static_assert(h());225}226 227namespace GH62462 {228 229class string {230public:231  char *mem;232  constexpr string() {233    this->mem = new char(1);234  }235  constexpr ~string() {236    delete this->mem;237  }238  constexpr unsigned size() const { return 4; }239};240 241 242template <unsigned N>243void test() {};244 245void f() {246    test<string().size()>();247}248 249}250 251namespace GH134820 {252struct S {253    char* c = new char;254    constexpr ~S() {255        delete c;256    }257    int i = 0;258};259 260int f() {261    if constexpr((S{}, true)) { // expected-warning{{left operand of comma operator has no effect}}262        return 1;263    }264    if constexpr(S s; (S{}, true)) { // expected-warning{{left operand of comma operator has no effect}}265        return 1;266    }267    if constexpr(S s; (s, true)) { // expected-warning{{left operand of comma operator has no effect}}268        return 1;269    }270    if constexpr(constexpr int _ = S{}.i; true) {271        return 1;272    }273    return 0;274}275 276template <typename T>277int f2() {278    if constexpr((T{}, true)) { // expected-warning{{left operand of comma operator has no effect}}279        return 1;280    }281    if constexpr(T s; (T{}, true)) { // expected-warning{{left operand of comma operator has no effect}}282        return 1;283    }284    if constexpr(T s; (s, true)) { // expected-warning{{left operand of comma operator has no effect}}285        return 1;286    }287    if constexpr(constexpr int _ = T{}.i; true) {288        return 1;289    }290    return 0;291}292 293void test() {294  f2<S>(); // expected-note {{in instantiation}}295}296 297}298namespace GH120197{299struct NonTrivialDtor {300  NonTrivialDtor() = default;301  NonTrivialDtor(const NonTrivialDtor&) = default;302  NonTrivialDtor(NonTrivialDtor&&) = default;303  NonTrivialDtor& operator=(const NonTrivialDtor&)  = default;304  NonTrivialDtor& operator=(NonTrivialDtor&&) = default;305  constexpr ~NonTrivialDtor() noexcept {}306};307 308static_assert(((void)NonTrivialDtor{}, true)); // passes309 310void f() {311  if constexpr ((void)NonTrivialDtor{}, true) {}312}313}314