// RUN: %clang_cc1 -std=c++2c -verify %s // RUN: %clang_cc1 -std=c++2c -verify %s -fexperimental-new-constant-interpreter namespace std { using size_t = decltype(sizeof(0)); } void *operator new(std::size_t, void *p) { return p; } void* operator new[] (std::size_t, void* p) {return p;} consteval int ok() { int i; new (&i) int(0); new (&i) int[1]{1}; new (static_cast(&i)) int(0); return 0; } consteval int conversion() { int i; new (static_cast(&i)) float(0); // expected-note@-1 {{placement new would change type of storage from 'int' to 'float'}} return 0; } consteval int indeterminate() { int * indeterminate; new (indeterminate) int(0); // expected-note@-1 {{read of uninitialized object is not allowed in a constant expression}} return 0; } consteval int array1() { int i[2]; new (&i) int[]{1,2}; new (&i) int[]{1}; new (&i) int(0); new (static_cast(&i)) int[]{1,2}; new (static_cast(&i)) int[]{1}; return 0; } consteval int array2() { int i[1]; new (&i) int[2]; //expected-note@-1 {{placement new would change type of storage from 'int[1]' to 'int[2]'}} return 0; } struct S{ int* i; constexpr S() : i(new int(42)) {} // #no-deallocation constexpr ~S() {delete i;} }; consteval void alloc() { S* s = new S(); s->~S(); new (s) S(); delete s; } consteval void alloc_err() { S* s = new S(); new (s) S(); delete s; } int a = ok(); int b = conversion(); // expected-error {{call to consteval function 'conversion' is not a constant expression}} \ // expected-note {{in call to 'conversion()'}} int c = indeterminate(); // expected-error {{call to consteval function 'indeterminate' is not a constant expression}} \ // expected-note {{in call to 'indeterminate()'}} int d = array1(); int e = array2(); // expected-error {{call to consteval function 'array2' is not a constant expression}} \ // expected-note {{in call to 'array2()'}} int alloc1 = (alloc(), 0); int alloc2 = (alloc_err(), 0); // expected-error {{call to consteval function 'alloc_err' is not a constant expression}} // expected-note@#no-deallocation {{allocation performed here was not deallocated}} constexpr int *intptr() { return new int; } constexpr bool yay() { int *ptr = new (intptr()) int(42); bool ret = *ptr == 42; delete ptr; return ret; } static_assert(yay()); constexpr bool blah() { int *ptr = new (intptr()) int[3]{ 1, 2, 3 }; // expected-note {{placement new would change type of storage from 'int' to 'int[3]'}} bool ret = ptr[0] == 1 && ptr[1] == 2 && ptr[2] == 3; delete [] ptr; return ret; } static_assert(blah()); // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'blah()'}} constexpr int *get_indeterminate() { int *evil; return evil; // expected-note {{read of uninitialized object is not allowed in a constant expression}} } constexpr bool bleh() { int *ptr = new (get_indeterminate()) int; // expected-note {{in call to 'get_indeterminate()'}} return true; } static_assert(bleh()); // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'bleh()'}} constexpr int modify_const_variable() { const int a = 10; new ((int *)&a) int(12); // expected-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}} return a; } static_assert(modify_const_variable()); // expected-error {{not an integral constant expression}} \ // expected-note {{in call to}} typedef const int T0; typedef T0 T1; constexpr T1 modify_const_variable_td() { T1 a = 10; new ((int *)&a) int(12); // expected-note {{modification of object of const-qualified type 'T1' (aka 'const int') is not allowed in a constant expression}} return a; } static_assert(modify_const_variable_td()); // expected-error {{not an integral constant expression}} \ // expected-note {{in call to}} template constexpr T modify_const_variable_tmpl() { T a = 10; new ((int *)&a) int(12); // expected-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}} return a; } static_assert(modify_const_variable_tmpl()); // expected-error {{not an integral constant expression}} \ // expected-note {{in call to}} namespace ModifyMutableMember { struct S { mutable int a {10}; }; constexpr int modify_mutable_member() { const S s; new ((int *)&s.a) int(12); return s.a; } static_assert(modify_mutable_member() == 12); }