1 // RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -fexperimental-new-constant-interpreter -verify=expected,both %s -DBYTECODE 2 // RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -verify=ref,both %s 3 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); 9 } 10 constexpr void deallocate(void *p) { 11 operator delete(p); 12 } 13 }; 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}} 19 20 } 21 } 22 23 void *operator new(std::size_t, void *p) { return p; } 24 void* operator new[] (std::size_t, void* p) {return p;} 25 26 27 consteval auto ok1() { 28 bool b; 29 new (&b) bool(true); 30 return b; 31 } 32 static_assert(ok1()); 33 34 consteval auto ok2() { 35 int b; 36 new (&b) int(12); 37 return b; 38 } 39 static_assert(ok2() == 12); 40 41 42 consteval auto ok3() { 43 float b; 44 new (&b) float(12.0); 45 return b; 46 } 47 static_assert(ok3() == 12.0); 48 49 50 consteval auto ok4() { 51 _BitInt(11) b; 52 new (&b) _BitInt(11)(37); 53 return b; 54 } 55 static_assert(ok4() == 37); 56 57 consteval int ok5() { 58 int i; 59 new (&i) int[1]{1}; 60 61 struct S { 62 int a; int b; 63 } s; 64 new (&s) S[1]{{12, 13}}; 65 66 return 25; 67 // return s.a + s.b; FIXME: Broken in the current interpreter. 68 } 69 static_assert(ok5() == 25); 70 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; 77 } 78 static_assert(ok5() == 1); // expected-error {{not an integral constant expression}} \ 79 // expected-note {{in call to}} 80 #endif 81 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]; 88 } 89 static_assert(ok6() == 100); 90 #endif 91 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]; 97 } 98 static_assert(ok6() == 300); 99 100 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; 105 } 106 static_assert(fail1() == 0); // both-error {{not an integral constant expression}} \ 107 // both-note {{in call to}} 108 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; 113 } 114 static_assert(fail2() == 0); // both-error {{not an integral constant expression}} \ 115 // both-note {{in call to}} 116 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; 121 } 122 static_assert(indeterminate() == 0); // both-error {{not an integral constant expression}} \ 123 // both-note {{in call to}} 124 125 consteval int array1() { 126 int i[2]; 127 new (&i) int[]{1,2}; 128 return i[0] + i[1]; 129 } 130 static_assert(array1() == 3); 131 132 consteval int array2() { 133 int i[2]; 134 new (static_cast<void*>(&i)) int[]{1,2}; 135 return i[0] + i[1]; 136 } 137 static_assert(array2() == 3); 138 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; 143 } 144 static_assert(array3() == 0); // both-error {{not an integral constant expression}} \ 145 // both-note {{in call to}} 146 147 consteval int array4() { 148 int i[2]; 149 new (&i) int[]{12}; 150 return i[0]; 151 } 152 static_assert(array4() == 12); 153 154 constexpr int *intptr() { 155 return new int; 156 } 157 constexpr bool yay() { 158 int *ptr = new (intptr()) int(42); 159 bool ret = *ptr == 42; 160 delete ptr; 161 return ret; 162 } 163 static_assert(yay()); 164 165 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; 171 } 172 static_assert(blah()); // both-error {{not an integral constant expression}} \ 173 // both-note {{in call to 'blah()'}} 174 175 176 constexpr int *get_indeterminate() { 177 int *evil; 178 return evil; // both-note {{read of uninitialized object is not allowed in a constant expression}} 179 } 180 181 constexpr bool bleh() { 182 int *ptr = new (get_indeterminate()) int; // both-note {{in call to 'get_indeterminate()'}} 183 return true; 184 } 185 static_assert(bleh()); // both-error {{not an integral constant expression}} \ 186 // both-note {{in call to 'bleh()'}} 187 188 namespace records { 189 class S { 190 public: 191 float f; 192 }; 193 194 constexpr bool record1() { 195 S s(13); 196 new (&s) S(42); 197 return s.f == 42; 198 } 199 static_assert(record1()); 200 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; 205 } 206 static_assert(record2()); // both-error {{not an integral constant expression}} \ 207 // both-note {{in call to}} 208 209 210 constexpr bool record3() { 211 S ss[3]; 212 213 new (&ss) S[]{{1}, {2}, {3}}; 214 215 return ss[0].f == 1 && ss[1].f == 2 && ss[2].f == 3; 216 } 217 static_assert(record3()); 218 219 struct F { 220 float f; 221 }; 222 struct R { 223 F f; 224 int a; 225 }; 226 constexpr bool record4() { 227 R r; 228 new (&r.f) F{42.0}; 229 new (&r.a) int(12); 230 231 return r.f.f == 42.0 && r.a == 12; 232 } 233 static_assert(record4()); 234 235 /// Destructor is NOT called. 236 struct A { 237 bool b; 238 constexpr ~A() { if (b) throw; } 239 }; 240 241 constexpr int foo() { 242 A a; 243 new (&a) A(true); 244 new (&a) A(false); 245 return 0; 246 } 247 static_assert(foo() == 0); 248 } 249 250 namespace ConstructAt { 251 struct S { 252 int a = 10; 253 float b = 1.0; 254 }; 255 256 constexpr bool ok1() { 257 S s; 258 259 std::construct_at<S>(&s); 260 return s.a == 10 && s.b == 1.0; 261 } 262 static_assert(ok1()); 263 264 struct S2 { 265 constexpr S2() { 266 (void)(1/0); // both-note {{division by zero}} \ 267 // both-warning {{division by zero is undefined}} 268 } 269 }; 270 271 constexpr bool ctorFail() { // 272 S2 *s = std::allocator<S2>().allocate(1); 273 std::construct_at<S2>(s); // both-note {{in call to}} 274 275 return true; 276 } 277 static_assert(ctorFail()); // both-error {{not an integral constant expression}} \ 278 // both-note {{in call to 'ctorFail()'}} 279 280 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; 285 } 286 static_assert(bad_construct_at_type()); // both-error {{not an integral constant expression}} \ 287 // both-note {{in call}} 288 289 constexpr bool bad_construct_at_subobject() { 290 struct X { int a, b; }; 291 union A { 292 int a; 293 X x; 294 }; 295 A a = {1}; 296 std::construct_at<int>(&a.x.a, 1); // both-note {{in call}} 297 return true; 298 } 299 static_assert(bad_construct_at_subobject()); // both-error{{not an integral constant expression}} \ 300 // both-note {{in call}} 301 } 302 303 namespace UsedToCrash { 304 struct S { 305 int* i; 306 constexpr S() : i(new int(42)) {} // #no-deallocation 307 constexpr ~S() {delete i;} 308 }; 309 consteval void alloc() { 310 S* s = new S(); 311 s->~S(); 312 new (s) S(); 313 delete s; 314 } 315 int alloc1 = (alloc(), 0); 316 } 317 318 constexpr bool change_union_member() { 319 union U { 320 int a; 321 int b; 322 }; 323 U u = {.a = 1}; 324 std::construct_at<int>(&u.b, 2); 325 return u.b == 2; 326 } 327 static_assert(change_union_member()); 328 329 namespace PR48606 { 330 struct A { mutable int n = 0; }; 331 332 constexpr bool f() { 333 A a; 334 A *p = &a; 335 p->~A(); 336 std::construct_at<A>(p); 337 return true; 338 } 339 static_assert(f()); 340 } 341 342 #ifdef BYTECODE 343 constexpr int N = [] // expected-error {{must be initialized by a constant expression}} \ 344 // expected-note {{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}} \ 345 // expected-note {{in call to}} 346 { 347 struct S { 348 int a[1]; 349 }; 350 S s; 351 ::new (s.a) int[1][2][3][4](); 352 return s.a[0]; 353 }(); 354 #endif 355