1 // RUN: %clang_cc1 -std=c++20 -verify -fconstexpr-steps=1024 -Wvla %s 2 3 namespace std { 4 using size_t = decltype(sizeof(0)); 5 } 6 operator new(std::size_t,void * p)7void *operator new(std::size_t, void *p) { return p; } 8 9 namespace std { 10 template<typename T> struct allocator { allocatestd::allocator11 constexpr T *allocate(size_t N) { 12 return (T*)operator new(sizeof(T) * N); // #alloc 13 } deallocatestd::allocator14 constexpr void deallocate(void *p) { 15 operator delete(p); 16 } 17 }; 18 template<typename T, typename ...Args> construct_at(void * p,Args &&...args)19 constexpr void construct_at(void *p, Args &&...args) { // #construct 20 new (p) T((Args&&)args...); 21 } 22 } 23 24 namespace GH63562 { 25 26 template <typename T> 27 struct S { SGH63562::S28 constexpr S(unsigned long long N) 29 : data(nullptr){ 30 data = alloc.allocate(N); // #call 31 for(std::size_t i = 0; i < N; i ++) 32 std::construct_at<T>(data + i, i); // #construct_call 33 } operator []GH63562::S34 constexpr T operator[](std::size_t i) const { 35 return data[i]; 36 } 37 ~SGH63562::S38 constexpr ~S() { 39 alloc.deallocate(data); 40 } 41 std::allocator<T> alloc; 42 T* data; 43 }; 44 45 // Only run these tests on 64 bits platforms 46 #if __LP64__ 47 constexpr std::size_t s = S<std::size_t>(~0UL)[42]; // expected-error {{constexpr variable 's' must be initialized by a constant expression}} \ 48 // expected-note-re@#call {{in call to 'this->alloc.allocate({{.*}})'}} \ 49 // expected-note-re@#alloc {{cannot allocate array; evaluated array bound {{.*}} is too large}} \ 50 // expected-note-re {{in call to 'S({{.*}})'}} 51 #endif 52 // Check that we do not try to fold very large arrays 53 std::size_t s2 = S<std::size_t>(~0UL)[42]; 54 std::size_t s3 = S<std::size_t>(~0ULL)[42]; 55 56 // We can allocate and initialize a small array 57 constexpr std::size_t ssmall = S<std::size_t>(100)[42]; 58 59 // We can allocate this array but we hikt the number of steps 60 constexpr std::size_t s4 = S<std::size_t>(1024)[42]; // expected-error {{constexpr variable 's4' must be initialized by a constant expression}} \ 61 // expected-note@#construct {{constexpr evaluation hit maximum step limit; possible infinite loop?}} \ 62 // expected-note@#construct_call {{in call}} \ 63 // expected-note {{in call}} 64 65 66 67 constexpr std::size_t s5 = S<std::size_t>(1025)[42]; // expected-error{{constexpr variable 's5' must be initialized by a constant expression}} \ 68 // expected-note@#alloc {{cannot allocate array; evaluated array bound 1025 exceeds the limit (1024); use '-fconstexpr-steps' to increase this limit}} \ 69 // expected-note@#call {{in call to 'this->alloc.allocate(1025)'}} \ 70 // expected-note {{in call}} 71 72 73 // Check we do not perform constant initialization in the presence 74 // of very large arrays (this used to crash) 75 76 template <auto N> stack_array()77constexpr int stack_array() { 78 [[maybe_unused]] char BIG[N] = {1}; // expected-note 3{{cannot allocate array; evaluated array bound 1025 exceeds the limit (1024); use '-fconstexpr-steps' to increase this limit}} 79 return BIG[N-1]; 80 } 81 82 int a = stack_array<~0U>(); 83 int c = stack_array<1024>(); 84 int d = stack_array<1025>(); 85 constexpr int e = stack_array<1024>(); 86 constexpr int f = stack_array<1025>(); // expected-error {{constexpr variable 'f' must be initialized by a constant expression}} \ 87 // expected-note {{in call}} ohno()88void ohno() { 89 int bar[stack_array<1024>()]; 90 int foo[stack_array<1025>()]; // expected-warning {{variable length arrays in C++ are a Clang extension}} \ 91 // expected-note {{in call to 'stack_array<1025>()'}} 92 93 constexpr int foo[stack_array<1025>()]; // expected-warning {{variable length arrays in C++ are a Clang extension}} \ 94 // expected-error {{constexpr variable cannot have non-literal type 'const int[stack_array<1025>()]'}} \ 95 // expected-note {{in call to 'stack_array<1025>()'}} 96 } 97 98 } 99