[PowerPC][NFC] Cleanup PPCCTRLoopsVerify pass
[llvm-project.git] / libcxx / test / support / count_new.h
blobed7bd50be209a12a087b7173937e18494156bbd5
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef COUNT_NEW_H
10 #define COUNT_NEW_H
12 # include <cstdlib>
13 # include <cassert>
14 # include <new>
16 #include "test_macros.h"
18 #if defined(TEST_HAS_SANITIZERS)
19 #define DISABLE_NEW_COUNT
20 #endif
22 namespace detail
24 TEST_NORETURN
25 inline void throw_bad_alloc_helper() {
26 #ifndef TEST_HAS_NO_EXCEPTIONS
27 throw std::bad_alloc();
28 #else
29 std::abort();
30 #endif
34 class MemCounter
36 public:
37 // Make MemCounter super hard to accidentally construct or copy.
38 class MemCounterCtorArg_ {};
39 explicit MemCounter(MemCounterCtorArg_) { reset(); }
41 private:
42 MemCounter(MemCounter const &);
43 MemCounter & operator=(MemCounter const &);
45 public:
46 // All checks return true when disable_checking is enabled.
47 static const bool disable_checking;
49 // Disallow any allocations from occurring. Useful for testing that
50 // code doesn't perform any allocations.
51 bool disable_allocations;
53 // number of allocations to throw after. Default (unsigned)-1. If
54 // throw_after has the default value it will never be decremented.
55 static const unsigned never_throw_value = static_cast<unsigned>(-1);
56 unsigned throw_after;
58 int outstanding_new;
59 int new_called;
60 int delete_called;
61 int aligned_new_called;
62 int aligned_delete_called;
63 std::size_t last_new_size;
64 std::size_t last_new_align;
65 std::size_t last_delete_align;
67 int outstanding_array_new;
68 int new_array_called;
69 int delete_array_called;
70 int aligned_new_array_called;
71 int aligned_delete_array_called;
72 std::size_t last_new_array_size;
73 std::size_t last_new_array_align;
74 std::size_t last_delete_array_align;
76 public:
77 void newCalled(std::size_t s)
79 assert(disable_allocations == false);
80 assert(s);
81 if (throw_after == 0) {
82 throw_after = never_throw_value;
83 detail::throw_bad_alloc_helper();
84 } else if (throw_after != never_throw_value) {
85 --throw_after;
87 ++new_called;
88 ++outstanding_new;
89 last_new_size = s;
92 void alignedNewCalled(std::size_t s, std::size_t a) {
93 newCalled(s);
94 ++aligned_new_called;
95 last_new_align = a;
98 void deleteCalled(void * p)
100 assert(p);
101 --outstanding_new;
102 ++delete_called;
105 void alignedDeleteCalled(void *p, std::size_t a) {
106 deleteCalled(p);
107 ++aligned_delete_called;
108 last_delete_align = a;
111 void newArrayCalled(std::size_t s)
113 assert(disable_allocations == false);
114 assert(s);
115 if (throw_after == 0) {
116 throw_after = never_throw_value;
117 detail::throw_bad_alloc_helper();
118 } else {
119 // don't decrement throw_after here. newCalled will end up doing that.
121 ++outstanding_array_new;
122 ++new_array_called;
123 last_new_array_size = s;
126 void alignedNewArrayCalled(std::size_t s, std::size_t a) {
127 newArrayCalled(s);
128 ++aligned_new_array_called;
129 last_new_array_align = a;
132 void deleteArrayCalled(void * p)
134 assert(p);
135 --outstanding_array_new;
136 ++delete_array_called;
139 void alignedDeleteArrayCalled(void * p, std::size_t a) {
140 deleteArrayCalled(p);
141 ++aligned_delete_array_called;
142 last_delete_array_align = a;
145 void disableAllocations()
147 disable_allocations = true;
150 void enableAllocations()
152 disable_allocations = false;
155 void reset()
157 disable_allocations = false;
158 throw_after = never_throw_value;
160 outstanding_new = 0;
161 new_called = 0;
162 delete_called = 0;
163 aligned_new_called = 0;
164 aligned_delete_called = 0;
165 last_new_size = 0;
166 last_new_align = 0;
168 outstanding_array_new = 0;
169 new_array_called = 0;
170 delete_array_called = 0;
171 aligned_new_array_called = 0;
172 aligned_delete_array_called = 0;
173 last_new_array_size = 0;
174 last_new_array_align = 0;
177 public:
178 bool checkOutstandingNewEq(int n) const
180 return disable_checking || n == outstanding_new;
183 bool checkOutstandingNewNotEq(int n) const
185 return disable_checking || n != outstanding_new;
188 bool checkNewCalledEq(int n) const
190 return disable_checking || n == new_called;
193 bool checkNewCalledNotEq(int n) const
195 return disable_checking || n != new_called;
198 bool checkNewCalledGreaterThan(int n) const
200 return disable_checking || new_called > n;
203 bool checkDeleteCalledEq(int n) const
205 return disable_checking || n == delete_called;
208 bool checkDeleteCalledNotEq(int n) const
210 return disable_checking || n != delete_called;
213 bool checkAlignedNewCalledEq(int n) const
215 return disable_checking || n == aligned_new_called;
218 bool checkAlignedNewCalledNotEq(int n) const
220 return disable_checking || n != aligned_new_called;
223 bool checkAlignedNewCalledGreaterThan(int n) const
225 return disable_checking || aligned_new_called > n;
228 bool checkAlignedDeleteCalledEq(int n) const
230 return disable_checking || n == aligned_delete_called;
233 bool checkAlignedDeleteCalledNotEq(int n) const
235 return disable_checking || n != aligned_delete_called;
238 bool checkLastNewSizeEq(std::size_t n) const
240 return disable_checking || n == last_new_size;
243 bool checkLastNewSizeNotEq(std::size_t n) const
245 return disable_checking || n != last_new_size;
248 bool checkLastNewAlignEq(std::size_t n) const
250 return disable_checking || n == last_new_align;
253 bool checkLastNewAlignNotEq(std::size_t n) const
255 return disable_checking || n != last_new_align;
258 bool checkLastDeleteAlignEq(std::size_t n) const
260 return disable_checking || n == last_delete_align;
263 bool checkLastDeleteAlignNotEq(std::size_t n) const
265 return disable_checking || n != last_delete_align;
268 bool checkOutstandingArrayNewEq(int n) const
270 return disable_checking || n == outstanding_array_new;
273 bool checkOutstandingArrayNewNotEq(int n) const
275 return disable_checking || n != outstanding_array_new;
278 bool checkNewArrayCalledEq(int n) const
280 return disable_checking || n == new_array_called;
283 bool checkNewArrayCalledNotEq(int n) const
285 return disable_checking || n != new_array_called;
288 bool checkDeleteArrayCalledEq(int n) const
290 return disable_checking || n == delete_array_called;
293 bool checkDeleteArrayCalledNotEq(int n) const
295 return disable_checking || n != delete_array_called;
298 bool checkAlignedNewArrayCalledEq(int n) const
300 return disable_checking || n == aligned_new_array_called;
303 bool checkAlignedNewArrayCalledNotEq(int n) const
305 return disable_checking || n != aligned_new_array_called;
308 bool checkAlignedNewArrayCalledGreaterThan(int n) const
310 return disable_checking || aligned_new_array_called > n;
313 bool checkAlignedDeleteArrayCalledEq(int n) const
315 return disable_checking || n == aligned_delete_array_called;
318 bool checkAlignedDeleteArrayCalledNotEq(int n) const
320 return disable_checking || n != aligned_delete_array_called;
323 bool checkLastNewArraySizeEq(std::size_t n) const
325 return disable_checking || n == last_new_array_size;
328 bool checkLastNewArraySizeNotEq(std::size_t n) const
330 return disable_checking || n != last_new_array_size;
333 bool checkLastNewArrayAlignEq(std::size_t n) const
335 return disable_checking || n == last_new_array_align;
338 bool checkLastNewArrayAlignNotEq(std::size_t n) const
340 return disable_checking || n != last_new_array_align;
344 #ifdef DISABLE_NEW_COUNT
345 const bool MemCounter::disable_checking = true;
346 #else
347 const bool MemCounter::disable_checking = false;
348 #endif
350 #ifdef _MSC_VER
351 #pragma warning(push)
352 #pragma warning(disable: 4640) // '%s' construction of local static object is not thread safe (/Zc:threadSafeInit-)
353 #endif // _MSC_VER
354 inline MemCounter* getGlobalMemCounter() {
355 static MemCounter counter((MemCounter::MemCounterCtorArg_()));
356 return &counter;
358 #ifdef _MSC_VER
359 #pragma warning(pop)
360 #endif
362 MemCounter &globalMemCounter = *getGlobalMemCounter();
364 #ifndef DISABLE_NEW_COUNT
365 void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
367 getGlobalMemCounter()->newCalled(s);
368 void* ret = std::malloc(s);
369 if (ret == nullptr)
370 detail::throw_bad_alloc_helper();
371 return ret;
374 void operator delete(void* p) TEST_NOEXCEPT
376 getGlobalMemCounter()->deleteCalled(p);
377 std::free(p);
380 void* operator new[](std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
382 getGlobalMemCounter()->newArrayCalled(s);
383 return operator new(s);
386 void operator delete[](void* p) TEST_NOEXCEPT
388 getGlobalMemCounter()->deleteArrayCalled(p);
389 operator delete(p);
392 #ifndef TEST_HAS_NO_ALIGNED_ALLOCATION
393 #if defined(_LIBCPP_MSVCRT_LIKE) || \
394 (!defined(_LIBCPP_VERSION) && defined(_WIN32))
395 #define USE_ALIGNED_ALLOC
396 #endif
398 void* operator new(std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
399 const std::size_t a = static_cast<std::size_t>(av);
400 getGlobalMemCounter()->alignedNewCalled(s, a);
401 void *ret;
402 #ifdef USE_ALIGNED_ALLOC
403 ret = _aligned_malloc(s, a);
404 #else
405 posix_memalign(&ret, a, s);
406 #endif
407 if (ret == nullptr)
408 detail::throw_bad_alloc_helper();
409 return ret;
412 void operator delete(void *p, std::align_val_t av) TEST_NOEXCEPT {
413 const std::size_t a = static_cast<std::size_t>(av);
414 getGlobalMemCounter()->alignedDeleteCalled(p, a);
415 if (p) {
416 #ifdef USE_ALIGNED_ALLOC
417 ::_aligned_free(p);
418 #else
419 ::free(p);
420 #endif
424 void* operator new[](std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
425 const std::size_t a = static_cast<std::size_t>(av);
426 getGlobalMemCounter()->alignedNewArrayCalled(s, a);
427 return operator new(s, av);
430 void operator delete[](void *p, std::align_val_t av) TEST_NOEXCEPT {
431 const std::size_t a = static_cast<std::size_t>(av);
432 getGlobalMemCounter()->alignedDeleteArrayCalled(p, a);
433 return operator delete(p, av);
436 #endif // TEST_HAS_NO_ALIGNED_ALLOCATION
438 #endif // DISABLE_NEW_COUNT
440 struct DisableAllocationGuard {
441 explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable)
443 // Don't re-disable if already disabled.
444 if (globalMemCounter.disable_allocations == true) m_disabled = false;
445 if (m_disabled) globalMemCounter.disableAllocations();
448 void release() {
449 if (m_disabled) globalMemCounter.enableAllocations();
450 m_disabled = false;
453 ~DisableAllocationGuard() {
454 release();
457 private:
458 bool m_disabled;
460 DisableAllocationGuard(DisableAllocationGuard const&);
461 DisableAllocationGuard& operator=(DisableAllocationGuard const&);
464 struct RequireAllocationGuard {
465 explicit RequireAllocationGuard(std::size_t RequireAtLeast = 1)
466 : m_req_alloc(RequireAtLeast),
467 m_new_count_on_init(globalMemCounter.new_called),
468 m_outstanding_new_on_init(globalMemCounter.outstanding_new),
469 m_exactly(false)
473 void requireAtLeast(std::size_t N) { m_req_alloc = N; m_exactly = false; }
474 void requireExactly(std::size_t N) { m_req_alloc = N; m_exactly = true; }
476 ~RequireAllocationGuard() {
477 assert(globalMemCounter.checkOutstandingNewEq(static_cast<int>(m_outstanding_new_on_init)));
478 std::size_t Expect = m_new_count_on_init + m_req_alloc;
479 assert(globalMemCounter.checkNewCalledEq(static_cast<int>(Expect)) ||
480 (!m_exactly && globalMemCounter.checkNewCalledGreaterThan(static_cast<int>(Expect))));
483 private:
484 std::size_t m_req_alloc;
485 const std::size_t m_new_count_on_init;
486 const std::size_t m_outstanding_new_on_init;
487 bool m_exactly;
488 RequireAllocationGuard(RequireAllocationGuard const&);
489 RequireAllocationGuard& operator=(RequireAllocationGuard const&);
492 #endif /* COUNT_NEW_H */