brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.2 KiB · 1c015da Raw
526 lines · cpp
1// RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -fexperimental-new-constant-interpreter -verify=expected,both %s -DBYTECODE2// RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -verify=ref,both %s3 4typedef __INT64_TYPE__ int64_t;5namespace std {6  using size_t = decltype(sizeof(0));7  template<typename T> struct allocator {8    constexpr T *allocate(size_t N) {9      return (T*)operator new(sizeof(T) * N);10    }11    constexpr void deallocate(void *p) {12      operator delete(p);13    }14  };15  template<typename T, typename ...Args>16  constexpr void construct_at(void *p, Args &&...args) {17    new (p) T((Args&&)args...); // both-note {{in call to}} \18                                // both-note {{placement new would change type of storage from 'int' to 'float'}} \19                                // both-note {{construction of subobject of member 'x' of union with active member 'a' is not allowed in a constant expression}} \20                                // both-note {{construction of temporary is not allowed}} \21                                // both-note {{construction of heap allocated object that has been deleted}} \22                                // both-note {{construction of subobject of object outside its lifetime is not allowed in a constant expression}}23  }24}25 26void *operator new(std::size_t, void *p) { return p; }27void* operator new[] (std::size_t, void* p) {return p;}28 29constexpr int no_lifetime_start = (*std::allocator<int>().allocate(1) = 1); // both-error {{constant expression}} \30                                                                            // both-note {{assignment to object outside its lifetime}}31 32consteval auto ok1() {33  bool b;34  new (&b) bool(true);35  return b;36}37static_assert(ok1());38 39consteval auto ok2() {40  int b;41  new (&b) int(12);42  return b;43}44static_assert(ok2() == 12);45 46 47consteval auto ok3() {48  float b;49  new (&b) float(12.0);50  return b;51}52static_assert(ok3() == 12.0);53 54 55consteval auto ok4() {56  _BitInt(11) b;57  new (&b) _BitInt(11)(37);58  return b;59}60static_assert(ok4() == 37);61 62consteval int ok5() {63  int i;64  new (&i) int[1]{1};65 66  struct S {67    int a; int b;68  } s;69  new (&s) S[1]{{12, 13}};70 71  return 25;72  // return s.a + s.b; FIXME: Broken in the current interpreter.73}74static_assert(ok5() == 25);75 76/// FIXME: Broken in both interpreters.77#if 078consteval int ok5() {79    int i;80    new (&i) int[1]{1}; // expected-note {{assignment to dereferenced one-past-the-end pointer}}81    return i;82}83static_assert(ok5() == 1); // expected-error {{not an integral constant expression}} \84                           // expected-note {{in call to}}85#endif86 87/// FIXME: Crashes the current interpreter.88#if 089consteval int ok6() {90    int i[2];91    new (&i) int(100);92    return i[0];93}94static_assert(ok6() == 100);95#endif96 97consteval int ok6() {98    int i[2];99    new (i) int(100);100    new (i + 1) int(200);101    return i[0] + i[1];102}103static_assert(ok6() == 300);104 105 106consteval auto fail1() {107  int b;108  new (&b) float(1.0); // both-note {{placement new would change type of storage from 'int' to 'float'}}109  return b;110}111static_assert(fail1() == 0); // both-error {{not an integral constant expression}} \112                             // both-note {{in call to}}113 114consteval int fail2() {115    int i;116    new (static_cast<void*>(&i)) float(0); // both-note {{placement new would change type of storage from 'int' to 'float'}}117    return 0;118}119static_assert(fail2() == 0); // both-error {{not an integral constant expression}} \120                             // both-note {{in call to}}121 122consteval int indeterminate() {123    int * indeterminate;124    new (indeterminate) int(0); // both-note {{read of uninitialized object is not allowed in a constant expression}}125    return 0;126}127static_assert(indeterminate() == 0); // both-error {{not an integral constant expression}} \128                                     // both-note {{in call to}}129 130consteval int array1() {131    int i[2];132    new (&i) int[]{1,2};133    return i[0] + i[1];134}135static_assert(array1() == 3);136 137consteval int array2() {138    int i[2];139    new (static_cast<void*>(&i)) int[]{1,2};140    return i[0] + i[1];141}142static_assert(array2() == 3);143 144consteval int array3() {145    int i[1];146    new (&i) int[2]; // both-note {{placement new would change type of storage from 'int[1]' to 'int[2]'}}147    return 0;148}149static_assert(array3() == 0); // both-error {{not an integral constant expression}} \150                              // both-note {{in call to}}151 152consteval int array4() {153    int i[2];154    new (&i) int[]{12};155    return i[0];156}157static_assert(array4() == 12);158 159constexpr int *intptr() {160  return new int;161}162constexpr bool yay() {163  int *ptr = new (intptr()) int(42);164  bool ret = *ptr == 42;165  delete ptr;166  return ret;167}168static_assert(yay());169 170 171constexpr bool blah() {172  int *ptr = new (intptr()) int[3]{ 1, 2, 3 }; // both-note {{placement new would change type of storage from 'int' to 'int[3]'}}173  bool ret = ptr[0] == 1 && ptr[1] == 2 && ptr[2] == 3;174  delete [] ptr;175  return ret;176}177static_assert(blah()); // both-error {{not an integral constant expression}} \178                       // both-note {{in call to 'blah()'}}179 180 181constexpr int *get_indeterminate() {182  int *evil;183  return evil; // both-note {{read of uninitialized object is not allowed in a constant expression}}184}185 186constexpr bool bleh() {187  int *ptr = new (get_indeterminate()) int;  // both-note {{in call to 'get_indeterminate()'}}188  return true;189}190static_assert(bleh()); // both-error {{not an integral constant expression}} \191                       // both-note {{in call to 'bleh()'}}192 193namespace records {194  class S {195  public:196    float f;197  };198 199  constexpr bool record1() {200    S s(13);201    new (&s) S(42);202    return s.f == 42;203  }204  static_assert(record1());205 206  S GlobalS;207  constexpr bool record2() {208    new (&GlobalS) S(42); // both-note {{a constant expression cannot modify an object that is visible outside that expression}}209    return GlobalS.f == 42;210  }211  static_assert(record2()); // both-error {{not an integral constant expression}} \212                            // both-note {{in call to}}213 214 215  constexpr bool record3() {216    S ss[3];217 218    new (&ss) S[]{{1}, {2}, {3}};219 220    return ss[0].f == 1 && ss[1].f == 2 && ss[2].f == 3;221  }222  static_assert(record3());223 224  struct F {225    float f;226  };227  struct R {228    F f;229    int a;230  };231  constexpr bool record4()  {232    R r;233    new (&r.f) F{42.0};234    new (&r.a) int(12);235 236    return r.f.f == 42.0 && r.a == 12;237  }238  static_assert(record4());239 240  /// Destructor is NOT called.241  struct A {242    bool b;243    constexpr ~A() { if (b) throw; }244  };245 246  constexpr int foo() {247    A a;248    new (&a) A(true);249    new (&a) A(false);250    return 0;251  }252  static_assert(foo() == 0);253}254 255namespace ConstructAt {256  struct S {257    int a = 10;258    float b = 1.0;259  };260 261  constexpr bool ok1() {262    S s;263 264    std::construct_at<S>(&s);265    return s.a == 10 && s.b == 1.0;266  }267  static_assert(ok1());268 269  struct S2 {270    constexpr S2() {271      (void)(1/0); // both-note {{division by zero}} \272                   // both-warning {{division by zero is undefined}}273    }274  };275 276  constexpr bool ctorFail() { //277    S2 *s = std::allocator<S2>().allocate(1);278    std::construct_at<S2>(s); // both-note {{in call to}}279 280    return true;281  }282  static_assert(ctorFail()); // both-error {{not an integral constant expression}} \283                             // both-note {{in call to 'ctorFail()'}}284 285 286  constexpr bool bad_construct_at_type() {287    int a;288    std::construct_at<float>(&a, 1.0f); // both-note {{in call to}}289    return true;290  }291  static_assert(bad_construct_at_type()); // both-error {{not an integral constant expression}} \292                                          // both-note {{in call}}293 294  constexpr bool bad_construct_at_subobject() {295    struct X { int a, b; };296    union A {297      int a;298      X x;299    };300    A a = {1};301    std::construct_at<int>(&a.x.a, 1); // both-note {{in call}}302    return true;303  }304  static_assert(bad_construct_at_subobject()); // both-error{{not an integral constant expression}} \305                                               // both-note {{in call}}306}307 308namespace UsedToCrash {309  struct S {310      int* i;311      constexpr S() : i(new int(42)) {} // #no-deallocation312      constexpr ~S() {delete i;}313  };314  consteval void alloc() {315      S* s = new S();316      s->~S();317      new (s) S();318      delete s;319  }320  int alloc1 = (alloc(), 0);321}322 323constexpr bool change_union_member() {324  union U {325    int a;326    int b;327  };328  U u = {.a = 1};329  std::construct_at<int>(&u.b, 2);330  return u.b == 2;331}332static_assert(change_union_member());333 334namespace PR48606 {335  struct A { mutable int n = 0; };336 337  constexpr bool f() {338    A a;339    A *p = &a;340    p->~A();341    std::construct_at<A>(p);342    return true;343  }344  static_assert(f());345}346 347/// This used to crash because of an assertion in the implementation348/// of the This instruction.349namespace ExplicitThisOnArrayElement {350  struct S {351    int a = 12;352    constexpr S(int a) {353      this->a = a;354    }355  };356 357  template <class _Tp, class... _Args>358  constexpr void construct_at(_Tp *__location, _Args &&...__args) {359    new (__location) _Tp(__args...);360  }361 362  constexpr bool foo() {363    auto *M = std::allocator<S>().allocate(13); // both-note {{allocation performed here was not deallocated}}364    construct_at(M, 12);365    return true;366  }367 368  static_assert(foo()); // both-error {{not an integral constant expression}}369}370 371#ifdef BYTECODE372constexpr int N = [] // expected-error {{must be initialized by a constant expression}} \373                     // expected-note {{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}} \374                     // expected-note {{in call to}}375{376    struct S {377        int a[1];378    };379    S s;380    ::new (s.a) int[1][2][3][4]();381    return s.a[0];382}();383#endif384 385namespace MemMove {386  constexpr int foo() {387    int *a = std::allocator<int>{}.allocate(1);388    new(a) int{123};389 390    int b;391    __builtin_memmove(&b, a, sizeof(int));392 393    std::allocator<int>{}.deallocate(a);394    return b;395  }396 397  static_assert(foo() == 123);398}399 400namespace Temp {401  constexpr int &&temporary = 0; // both-note {{created here}}402  static_assert((std::construct_at<int>(&temporary, 1), true)); // both-error{{not an integral constant expression}} \403                                                                // both-note {{in call}}404}405 406namespace PlacementNewAfterDelete {407  constexpr bool construct_after_lifetime() {408    int *p = new int;409    delete p;410    std::construct_at<int>(p); // both-note {{in call}}411    return true;412  }413  static_assert(construct_after_lifetime()); // both-error {{}} \414                                             // both-note {{in call}}415}416 417namespace SubObj {418  constexpr bool construct_after_lifetime_2() {419    struct A { struct B {} b; };420    A a;421    a.~A();422    std::construct_at<A::B>(&a.b); // both-note {{in call}}423    return true;424  }425  static_assert(construct_after_lifetime_2()); // both-error {{}} both-note {{in call}}426}427 428namespace RecursiveLifetimeStart {429  struct B {430    int b;431  };432 433  struct A {434    B b;435    int a;436  };437 438  constexpr int foo() {439    A a;440    a.~A();441 442    new (&a) A();443    a.a = 10;444    a.b.b = 12;445    return a.a;446  }447  static_assert(foo() == 10);448}449 450namespace ArrayRoot {451  struct S {452    int a;453  };454  constexpr int foo() {455    S* ss = std::allocator<S>().allocate(2);456    new (ss) S{};457    new (ss + 1) S{};458 459    S* ps = &ss[2];460    ps = ss;461    ps->~S();462 463    std::allocator<S>().deallocate(ss);464    return 0;465  }466 467  static_assert(foo() == 0);468}469 470namespace bitcast {471  template <typename F, typename T>472  constexpr T bit_cast(const F &f) {473    return __builtin_bit_cast(T, f);474  }475  constexpr int foo() {476    double *d = std::allocator<double>{}.allocate(2);477    std::construct_at<double>(d, 0);478 479    double &dd = *d;480 481    int64_t i = bit_cast<double, int64_t>(*d);482 483 484    std::allocator<double>{}.deallocate(d);485    return i;486  }487  static_assert(foo() == 0);488}489 490constexpr int modify_const_variable() {491  const int a = 10;492  new ((int *)&a) int(12); // both-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}}493  return a;494}495static_assert(modify_const_variable()); // both-error {{not an integral constant expression}} \496                                        // both-note {{in call to}}497 498constexpr int nullDest() {499  new (nullptr) int{12}; // both-note {{construction of dereferenced null pointer}}500  return 0;501}502static_assert(nullDest() == 0); // both-error {{not an integral constant expression}} \503                                // both-note {{in call to}}504 505constexpr int nullArrayDest() {506  new (nullptr) int{12}; // both-note {{construction of dereferenced null pointer}}507  return 0;508}509static_assert(nullArrayDest() == 0); // both-error {{not an integral constant expression}} \510                                     // both-note {{in call to}}511 512constexpr int intDest() {513  new ((void*)2) int{3}; // both-note {{cast that performs the conversions of a reinterpret_cast}}514  return 0;515}516static_assert(intDest() == 0); // both-error {{not an integral constant expression}} \517                               // both-note {{in call to}}518 519constexpr int intDestArray() {520  new ((void*)2) int[4]; // both-note {{cast that performs the conversions of a reinterpret_cast}}521  return 0;522}523static_assert(intDestArray() == 0); // both-error {{not an integral constant expression}} \524                                    // both-note {{in call to}}525 526