[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / AST / ByteCode / placement-new.cpp
blob56f54ff168f3e858b5797eefea78450581ca5422
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
4 namespace std {
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) {
11 operator delete(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() {
28 bool b;
29 new (&b) bool(true);
30 return b;
32 static_assert(ok1());
34 consteval auto ok2() {
35 int b;
36 new (&b) int(12);
37 return b;
39 static_assert(ok2() == 12);
42 consteval auto ok3() {
43 float b;
44 new (&b) float(12.0);
45 return b;
47 static_assert(ok3() == 12.0);
50 consteval auto ok4() {
51 _BitInt(11) b;
52 new (&b) _BitInt(11)(37);
53 return b;
55 static_assert(ok4() == 37);
57 consteval int ok5() {
58 int i;
59 new (&i) int[1]{1};
61 struct S {
62 int a; int b;
63 } s;
64 new (&s) S[1]{{12, 13}};
66 return 25;
67 // return s.a + s.b; FIXME: Broken in the current interpreter.
69 static_assert(ok5() == 25);
71 /// FIXME: Broken in both interpreters.
72 #if 0
73 consteval int ok5() {
74 int i;
75 new (&i) int[1]{1}; // expected-note {{assignment to dereferenced one-past-the-end pointer}}
76 return i;
78 static_assert(ok5() == 1); // expected-error {{not an integral constant expression}} \
79 // expected-note {{in call to}}
80 #endif
82 /// FIXME: Crashes the current interpreter.
83 #if 0
84 consteval int ok6() {
85 int i[2];
86 new (&i) int(100);
87 return i[0];
89 static_assert(ok6() == 100);
90 #endif
92 consteval int ok6() {
93 int i[2];
94 new (i) int(100);
95 new (i + 1) int(200);
96 return i[0] + i[1];
98 static_assert(ok6() == 300);
101 consteval auto fail1() {
102 int b;
103 new (&b) float(1.0); // both-note {{placement new would change type of storage from 'int' to 'float'}}
104 return b;
106 static_assert(fail1() == 0); // both-error {{not an integral constant expression}} \
107 // both-note {{in call to}}
109 consteval int fail2() {
110 int i;
111 new (static_cast<void*>(&i)) float(0); // both-note {{placement new would change type of storage from 'int' to 'float'}}
112 return 0;
114 static_assert(fail2() == 0); // both-error {{not an integral constant expression}} \
115 // both-note {{in call to}}
117 consteval int indeterminate() {
118 int * indeterminate;
119 new (indeterminate) int(0); // both-note {{read of uninitialized object is not allowed in a constant expression}}
120 return 0;
122 static_assert(indeterminate() == 0); // both-error {{not an integral constant expression}} \
123 // both-note {{in call to}}
125 consteval int array1() {
126 int i[2];
127 new (&i) int[]{1,2};
128 return i[0] + i[1];
130 static_assert(array1() == 3);
132 consteval int array2() {
133 int i[2];
134 new (static_cast<void*>(&i)) int[]{1,2};
135 return i[0] + i[1];
137 static_assert(array2() == 3);
139 consteval int array3() {
140 int i[1];
141 new (&i) int[2]; // both-note {{placement new would change type of storage from 'int[1]' to 'int[2]'}}
142 return 0;
144 static_assert(array3() == 0); // both-error {{not an integral constant expression}} \
145 // both-note {{in call to}}
147 consteval int array4() {
148 int i[2];
149 new (&i) int[]{12};
150 return i[0];
152 static_assert(array4() == 12);
154 constexpr int *intptr() {
155 return new int;
157 constexpr bool yay() {
158 int *ptr = new (intptr()) int(42);
159 bool ret = *ptr == 42;
160 delete ptr;
161 return ret;
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;
169 delete [] ptr;
170 return ret;
172 static_assert(blah()); // both-error {{not an integral constant expression}} \
173 // both-note {{in call to 'blah()'}}
176 constexpr int *get_indeterminate() {
177 int *evil;
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()'}}
183 return true;
185 static_assert(bleh()); // both-error {{not an integral constant expression}} \
186 // both-note {{in call to 'bleh()'}}
188 namespace records {
189 class S {
190 public:
191 float f;
194 constexpr bool record1() {
195 S s(13);
196 new (&s) S(42);
197 return s.f == 42;
199 static_assert(record1());
201 S GlobalS;
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() {
211 S ss[3];
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());
219 struct F {
220 float f;
222 struct R {
223 F f;
224 int a;
226 constexpr bool record4() {
227 R r;
228 new (&r.f) F{42.0};
229 new (&r.a) int(12);
231 return r.f.f == 42.0 && r.a == 12;
233 static_assert(record4());
235 /// Destructor is NOT called.
236 struct A {
237 bool b;
238 constexpr ~A() { if (b) throw; }
241 constexpr int foo() {
242 A a;
243 new (&a) A(true);
244 new (&a) A(false);
245 return 0;
247 static_assert(foo() == 0);
250 namespace ConstructAt {
251 struct S {
252 int a = 10;
253 float b = 1.0;
256 constexpr bool ok1() {
257 S s;
259 std::construct_at<S>(&s);
260 return s.a == 10 && s.b == 1.0;
262 static_assert(ok1());
264 struct S2 {
265 constexpr S2() {
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}}
275 return true;
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() {
282 int a;
283 std::construct_at<float>(&a, 1.0f); // both-note {{in call to}}
284 return true;
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; };
291 union A {
292 int a;
293 X x;
295 A a = {1};
296 std::construct_at<int>(&a.x.a, 1); // both-note {{in call}}
297 return true;
299 static_assert(bad_construct_at_subobject()); // both-error{{not an integral constant expression}} \
300 // both-note {{in call}}
303 namespace UsedToCrash {
304 struct S {
305 int* i;
306 constexpr S() : i(new int(42)) {} // #no-deallocation
307 constexpr ~S() {delete i;}
309 consteval void alloc() {
310 S* s = new S();
311 s->~S();
312 new (s) S();
313 delete s;
315 int alloc1 = (alloc(), 0);
318 constexpr bool change_union_member() {
319 union U {
320 int a;
321 int b;
323 U u = {.a = 1};
324 std::construct_at<int>(&u.b, 2);
325 return u.b == 2;
327 static_assert(change_union_member());
329 namespace PR48606 {
330 struct A { mutable int n = 0; };
332 constexpr bool f() {
333 A a;
334 A *p = &a;
335 p->~A();
336 std::construct_at<A>(p);
337 return true;
339 static_assert(f());