1 // RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -fexperimental-new-constant-interpreter -verify=expected,both %s
2 // RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -verify=ref,both %s
5 using size_t = decltype(sizeof(0));
6 template<typename T
> struct allocator
{
7 constexpr T
*allocate(size_t N
) {
8 return (T
*)operator new(sizeof(T
) * N
);
10 constexpr void deallocate(void *p
) {
14 template<typename T
, typename
...Args
>
15 constexpr void construct_at(void *p
, Args
&&...args
) {
16 new (p
) T((Args
&&)args
...); // both-note {{in call to}} \
17 // both-note {{placement new would change type of storage from 'int' to 'float'}} \
18 // both-note {{construction of subobject of member 'x' of union with active member 'a' is not allowed in a constant expression}}
23 void *operator new(std::size_t, void *p
) { return p
; }
24 void* operator new[] (std::size_t, void* p
) {return p
;}
27 consteval
auto ok1() {
34 consteval
auto ok2() {
39 static_assert(ok2() == 12);
42 consteval
auto ok3() {
47 static_assert(ok3() == 12.0);
50 consteval
auto ok4() {
52 new (&b
) _BitInt(11)(37);
55 static_assert(ok4() == 37);
64 new (&s
) S
[1]{{12, 13}};
67 // return s.a + s.b; FIXME: Broken in the current interpreter.
69 static_assert(ok5() == 25);
71 /// FIXME: Broken in both interpreters.
75 new (&i
) int[1]{1}; // expected-note {{assignment to dereferenced one-past-the-end pointer}}
78 static_assert(ok5() == 1); // expected-error {{not an integral constant expression}} \
79 // expected-note {{in call to}}
82 /// FIXME: Crashes the current interpreter.
89 static_assert(ok6() == 100);
98 static_assert(ok6() == 300);
101 consteval
auto fail1() {
103 new (&b
) float(1.0); // both-note {{placement new would change type of storage from 'int' to 'float'}}
106 static_assert(fail1() == 0); // both-error {{not an integral constant expression}} \
107 // both-note {{in call to}}
109 consteval
int fail2() {
111 new (static_cast<void*>(&i
)) float(0); // both-note {{placement new would change type of storage from 'int' to 'float'}}
114 static_assert(fail2() == 0); // both-error {{not an integral constant expression}} \
115 // both-note {{in call to}}
117 consteval
int indeterminate() {
119 new (indeterminate
) int(0); // both-note {{read of uninitialized object is not allowed in a constant expression}}
122 static_assert(indeterminate() == 0); // both-error {{not an integral constant expression}} \
123 // both-note {{in call to}}
125 consteval
int array1() {
130 static_assert(array1() == 3);
132 consteval
int array2() {
134 new (static_cast<void*>(&i
)) int[]{1,2};
137 static_assert(array2() == 3);
139 consteval
int array3() {
141 new (&i
) int[2]; // both-note {{placement new would change type of storage from 'int[1]' to 'int[2]'}}
144 static_assert(array3() == 0); // both-error {{not an integral constant expression}} \
145 // both-note {{in call to}}
147 consteval
int array4() {
152 static_assert(array4() == 12);
154 constexpr int *intptr() {
157 constexpr bool yay() {
158 int *ptr
= new (intptr()) int(42);
159 bool ret
= *ptr
== 42;
163 static_assert(yay());
166 constexpr bool blah() {
167 int *ptr
= new (intptr()) int[3]{ 1, 2, 3 }; // both-note {{placement new would change type of storage from 'int' to 'int[3]'}}
168 bool ret
= ptr
[0] == 1 && ptr
[1] == 2 && ptr
[2] == 3;
172 static_assert(blah()); // both-error {{not an integral constant expression}} \
173 // both-note {{in call to 'blah()'}}
176 constexpr int *get_indeterminate() {
178 return evil
; // both-note {{read of uninitialized object is not allowed in a constant expression}}
181 constexpr bool bleh() {
182 int *ptr
= new (get_indeterminate()) int; // both-note {{in call to 'get_indeterminate()'}}
185 static_assert(bleh()); // both-error {{not an integral constant expression}} \
186 // both-note {{in call to 'bleh()'}}
194 constexpr bool record1() {
199 static_assert(record1());
202 constexpr bool record2() {
203 new (&GlobalS
) S(42); // both-note {{a constant expression cannot modify an object that is visible outside that expression}}
204 return GlobalS
.f
== 42;
206 static_assert(record2()); // both-error {{not an integral constant expression}} \
207 // both-note {{in call to}}
210 constexpr bool record3() {
213 new (&ss
) S
[]{{1}, {2}, {3}};
215 return ss
[0].f
== 1 && ss
[1].f
== 2 && ss
[2].f
== 3;
217 static_assert(record3());
226 constexpr bool record4() {
231 return r
.f
.f
== 42.0 && r
.a
== 12;
233 static_assert(record4());
235 /// Destructor is NOT called.
238 constexpr ~A() { if (b
) throw; }
241 constexpr int foo() {
247 static_assert(foo() == 0);
250 namespace ConstructAt
{
256 constexpr bool ok1() {
259 std::construct_at
<S
>(&s
);
260 return s
.a
== 10 && s
.b
== 1.0;
262 static_assert(ok1());
266 (void)(1/0); // both-note {{division by zero}} \
267 // both-warning {{division by zero is undefined}}
271 constexpr bool ctorFail() { //
272 S2
*s
= std::allocator
<S2
>().allocate(1);
273 std::construct_at
<S2
>(s
); // both-note {{in call to}}
277 static_assert(ctorFail()); // both-error {{not an integral constant expression}} \
278 // both-note {{in call to 'ctorFail()'}}
281 constexpr bool bad_construct_at_type() {
283 std::construct_at
<float>(&a
, 1.0f
); // both-note {{in call to}}
286 static_assert(bad_construct_at_type()); // both-error {{not an integral constant expression}} \
287 // both-note {{in call}}
289 constexpr bool bad_construct_at_subobject() {
290 struct X
{ int a
, b
; };
296 std::construct_at
<int>(&a
.x
.a
, 1); // both-note {{in call}}
299 static_assert(bad_construct_at_subobject()); // both-error{{not an integral constant expression}} \
300 // both-note {{in call}}
303 namespace UsedToCrash
{
306 constexpr S() : i(new int(42)) {} // #no-deallocation
307 constexpr ~S() {delete i
;}
309 consteval
void alloc() {
315 int alloc1
= (alloc(), 0);
318 constexpr bool change_union_member() {
324 std::construct_at
<int>(&u
.b
, 2);
327 static_assert(change_union_member());
330 struct A
{ mutable int n
= 0; };
336 std::construct_at
<A
>(p
);