aboutsummaryrefslogtreecommitdiff
path: root/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp
blob: 8bcb4d45d4af8bffb8715a7a60de64659cb1cfe3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// RUN: %clang_cc1 -std=c++20 -verify -fconstexpr-steps=1024 -Wvla %s

namespace std {
  using size_t = decltype(sizeof(0));
}

void *operator new(std::size_t, void *p) { return p; }

namespace std {
  template<typename T> struct allocator {
    constexpr T *allocate(size_t N) {
      return (T*)operator new(sizeof(T) * N); // #alloc
    }
    constexpr void deallocate(void *p) {
      operator delete(p);
    }
  };
  template<typename T, typename ...Args>
  constexpr void construct_at(void *p, Args &&...args) { // #construct
    new (p) T((Args&&)args...);
  }
}

namespace GH63562 {

template <typename T>
struct S {
    constexpr S(unsigned long long N)
    : data(nullptr){
        data = alloc.allocate(N);  // #call
        for(std::size_t i = 0; i < N; i ++)
            std::construct_at<T>(data + i, i); // #construct_call
    }
    constexpr T operator[](std::size_t i) const {
      return data[i];
    }

    constexpr ~S() {
        alloc.deallocate(data);
    }
    std::allocator<T> alloc;
    T* data;
};

// Only run these tests on 64 bits platforms
#if __LP64__
constexpr std::size_t s = S<std::size_t>(~0UL)[42]; // expected-error {{constexpr variable 's' must be initialized by a constant expression}} \
                                           // expected-note-re@#call {{in call to 'this->alloc.allocate({{.*}})'}} \
                                           // expected-note-re@#alloc {{cannot allocate array; evaluated array bound {{.*}} is too large}} \
                                           // expected-note-re {{in call to 'S({{.*}})'}}
#endif
// Check that we do not try to fold very large arrays
std::size_t s2 = S<std::size_t>(~0UL)[42];
std::size_t s3 = S<std::size_t>(~0ULL)[42];

// We can allocate and initialize a small array
constexpr std::size_t ssmall = S<std::size_t>(100)[42];

// We can allocate this array but we hikt the number of steps
constexpr std::size_t s4 = S<std::size_t>(1024)[42]; // expected-error {{constexpr variable 's4' must be initialized by a constant expression}} \
                                   // expected-note@#construct {{constexpr evaluation hit maximum step limit; possible infinite loop?}} \
                                   // expected-note@#construct_call {{in call}} \
                                   // expected-note {{in call}}



constexpr std::size_t s5 = S<std::size_t>(1025)[42]; // expected-error{{constexpr variable 's5' must be initialized by a constant expression}} \
                                   // expected-note@#alloc {{cannot allocate array; evaluated array bound 1025 exceeds the limit (1024); use '-fconstexpr-steps' to increase this limit}} \
                                   // expected-note@#call {{in call to 'this->alloc.allocate(1025)'}} \
                                   // expected-note {{in call}}


// Check we do not perform constant initialization in the presence
// of very large arrays (this used to crash)

template <auto N>
constexpr int stack_array() {
    [[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}}
    return BIG[N-1];
}

int a = stack_array<~0U>();
int c = stack_array<1024>();
int d = stack_array<1025>();
constexpr int e = stack_array<1024>();
constexpr int f = stack_array<1025>(); // expected-error {{constexpr variable 'f' must be initialized by a constant expression}} \
                                       //  expected-note {{in call}}
void ohno() {
  int bar[stack_array<1024>()];
  int foo[stack_array<1025>()]; // expected-warning {{variable length arrays in C++ are a Clang extension}} \
                                // expected-note {{in call to 'stack_array<1025>()'}}

  constexpr int foo[stack_array<1025>()]; // expected-warning {{variable length arrays in C++ are a Clang extension}} \
                                          // expected-error {{constexpr variable cannot have non-literal type 'const int[stack_array<1025>()]'}} \
                                          // expected-note {{in call to 'stack_array<1025>()'}}
}

}