xref: /llvm-project/libcxx/test/support/count_new.h (revision 748023dc3210533df2c1c6efc8af1b5954493701)
1cc89063bSNico Weber //===----------------------------------------------------------------------===//
2cc89063bSNico Weber //
3cc89063bSNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4cc89063bSNico Weber // See https://llvm.org/LICENSE.txt for license information.
5cc89063bSNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cc89063bSNico Weber //
7cc89063bSNico Weber //===----------------------------------------------------------------------===//
8cc89063bSNico Weber 
9cc89063bSNico Weber #ifndef COUNT_NEW_H
10cc89063bSNico Weber #define COUNT_NEW_H
11cc89063bSNico Weber 
12b935ab8eSNikolas Klauser #include <algorithm>
13cc89063bSNico Weber #include <cassert>
1431eeba3fSNikolas Klauser #include <cerrno>
15b935ab8eSNikolas Klauser #include <cstdlib>
16cc89063bSNico Weber #include <new>
17e0a66116SNikolas Klauser #include <type_traits>
18cc89063bSNico Weber 
19cc89063bSNico Weber #include "test_macros.h"
20cc89063bSNico Weber 
21cc89063bSNico Weber #if defined(TEST_HAS_SANITIZERS)
22cc89063bSNico Weber #define DISABLE_NEW_COUNT
23cc89063bSNico Weber #endif
24cc89063bSNico Weber 
25cc89063bSNico Weber namespace detail
26cc89063bSNico Weber {
27*748023dcSNikolas Klauser [[noreturn]] inline void throw_bad_alloc_helper() {
28cc89063bSNico Weber #ifndef TEST_HAS_NO_EXCEPTIONS
29cc89063bSNico Weber   throw std::bad_alloc();
30cc89063bSNico Weber #else
31cc89063bSNico Weber        std::abort();
32cc89063bSNico Weber #endif
33cc89063bSNico Weber }
34cc89063bSNico Weber }
35cc89063bSNico Weber 
36cc89063bSNico Weber class MemCounter
37cc89063bSNico Weber {
38cc89063bSNico Weber public:
39cc89063bSNico Weber     // Make MemCounter super hard to accidentally construct or copy.
40cc89063bSNico Weber     class MemCounterCtorArg_ {};
41cc89063bSNico Weber     explicit MemCounter(MemCounterCtorArg_) { reset(); }
42cc89063bSNico Weber 
43cc89063bSNico Weber private:
44cc89063bSNico Weber     MemCounter(MemCounter const &);
45cc89063bSNico Weber     MemCounter & operator=(MemCounter const &);
46cc89063bSNico Weber 
47cc89063bSNico Weber public:
48cc89063bSNico Weber     // All checks return true when disable_checking is enabled.
49cc89063bSNico Weber     static const bool disable_checking;
50cc89063bSNico Weber 
51cc89063bSNico Weber     // Disallow any allocations from occurring. Useful for testing that
52cc89063bSNico Weber     // code doesn't perform any allocations.
53cc89063bSNico Weber     bool disable_allocations;
54cc89063bSNico Weber 
55cc89063bSNico Weber     // number of allocations to throw after. Default (unsigned)-1. If
56cc89063bSNico Weber     // throw_after has the default value it will never be decremented.
57cc89063bSNico Weber     static const unsigned never_throw_value = static_cast<unsigned>(-1);
58cc89063bSNico Weber     unsigned throw_after;
59cc89063bSNico Weber 
60cc89063bSNico Weber     int outstanding_new;
61cc89063bSNico Weber     int new_called;
62cc89063bSNico Weber     int delete_called;
63cc89063bSNico Weber     int aligned_new_called;
64cc89063bSNico Weber     int aligned_delete_called;
65cc89063bSNico Weber     std::size_t last_new_size;
66cc89063bSNico Weber     std::size_t last_new_align;
67cc89063bSNico Weber     std::size_t last_delete_align;
68cc89063bSNico Weber 
69cc89063bSNico Weber     int outstanding_array_new;
70cc89063bSNico Weber     int new_array_called;
71cc89063bSNico Weber     int delete_array_called;
72cc89063bSNico Weber     int aligned_new_array_called;
73cc89063bSNico Weber     int aligned_delete_array_called;
74cc89063bSNico Weber     std::size_t last_new_array_size;
75cc89063bSNico Weber     std::size_t last_new_array_align;
76cc89063bSNico Weber     std::size_t last_delete_array_align;
77cc89063bSNico Weber 
78cc89063bSNico Weber public:
79cc89063bSNico Weber     void newCalled(std::size_t s)
80cc89063bSNico Weber     {
81cc89063bSNico Weber         assert(disable_allocations == false);
82cc89063bSNico Weber         if (throw_after == 0) {
83cc89063bSNico Weber             throw_after = never_throw_value;
84cc89063bSNico Weber             detail::throw_bad_alloc_helper();
85cc89063bSNico Weber         } else if (throw_after != never_throw_value) {
86cc89063bSNico Weber             --throw_after;
87cc89063bSNico Weber         }
88cc89063bSNico Weber         ++new_called;
89cc89063bSNico Weber         ++outstanding_new;
90cc89063bSNico Weber         last_new_size = s;
91cc89063bSNico Weber     }
92cc89063bSNico Weber 
93cc89063bSNico Weber     void alignedNewCalled(std::size_t s, std::size_t a) {
94cc89063bSNico Weber       newCalled(s);
95cc89063bSNico Weber       ++aligned_new_called;
96cc89063bSNico Weber       last_new_align = a;
97cc89063bSNico Weber     }
98cc89063bSNico Weber 
99cc89063bSNico Weber     void deleteCalled(void * p)
100cc89063bSNico Weber     {
1014e112e5cSNikolas Klauser       if (p) {
102cc89063bSNico Weber         --outstanding_new;
103cc89063bSNico Weber         ++delete_called;
104cc89063bSNico Weber       }
1054e112e5cSNikolas Klauser     }
106cc89063bSNico Weber 
107cc89063bSNico Weber     void alignedDeleteCalled(void *p, std::size_t a) {
1084e112e5cSNikolas Klauser       if (p) {
109cc89063bSNico Weber         deleteCalled(p);
110cc89063bSNico Weber         ++aligned_delete_called;
111cc89063bSNico Weber         last_delete_align = a;
112cc89063bSNico Weber       }
1134e112e5cSNikolas Klauser     }
114cc89063bSNico Weber 
115cc89063bSNico Weber     void newArrayCalled(std::size_t s)
116cc89063bSNico Weber     {
117cc89063bSNico Weber         assert(disable_allocations == false);
118cc89063bSNico Weber         if (throw_after == 0) {
119cc89063bSNico Weber             throw_after = never_throw_value;
120cc89063bSNico Weber             detail::throw_bad_alloc_helper();
121cc89063bSNico Weber         } else {
122cc89063bSNico Weber             // don't decrement throw_after here. newCalled will end up doing that.
123cc89063bSNico Weber         }
124cc89063bSNico Weber         ++outstanding_array_new;
125cc89063bSNico Weber         ++new_array_called;
126cc89063bSNico Weber         last_new_array_size = s;
127cc89063bSNico Weber     }
128cc89063bSNico Weber 
129cc89063bSNico Weber     void alignedNewArrayCalled(std::size_t s, std::size_t a) {
130cc89063bSNico Weber       newArrayCalled(s);
131cc89063bSNico Weber       ++aligned_new_array_called;
132cc89063bSNico Weber       last_new_array_align = a;
133cc89063bSNico Weber     }
134cc89063bSNico Weber 
135cc89063bSNico Weber     void deleteArrayCalled(void * p)
136cc89063bSNico Weber     {
137cc89063bSNico Weber         assert(p);
138cc89063bSNico Weber         --outstanding_array_new;
139cc89063bSNico Weber         ++delete_array_called;
140cc89063bSNico Weber     }
141cc89063bSNico Weber 
142cc89063bSNico Weber     void alignedDeleteArrayCalled(void * p, std::size_t a) {
143cc89063bSNico Weber       deleteArrayCalled(p);
144cc89063bSNico Weber       ++aligned_delete_array_called;
145cc89063bSNico Weber       last_delete_array_align = a;
146cc89063bSNico Weber     }
147cc89063bSNico Weber 
148cc89063bSNico Weber     void disableAllocations()
149cc89063bSNico Weber     {
150cc89063bSNico Weber         disable_allocations = true;
151cc89063bSNico Weber     }
152cc89063bSNico Weber 
153cc89063bSNico Weber     void enableAllocations()
154cc89063bSNico Weber     {
155cc89063bSNico Weber         disable_allocations = false;
156cc89063bSNico Weber     }
157cc89063bSNico Weber 
158cc89063bSNico Weber     void reset()
159cc89063bSNico Weber     {
160cc89063bSNico Weber         disable_allocations = false;
161cc89063bSNico Weber         throw_after = never_throw_value;
162cc89063bSNico Weber 
163cc89063bSNico Weber         outstanding_new = 0;
164cc89063bSNico Weber         new_called = 0;
165cc89063bSNico Weber         delete_called = 0;
166cc89063bSNico Weber         aligned_new_called = 0;
167cc89063bSNico Weber         aligned_delete_called = 0;
168cc89063bSNico Weber         last_new_size = 0;
169cc89063bSNico Weber         last_new_align = 0;
170cc89063bSNico Weber 
171cc89063bSNico Weber         outstanding_array_new = 0;
172cc89063bSNico Weber         new_array_called = 0;
173cc89063bSNico Weber         delete_array_called = 0;
174cc89063bSNico Weber         aligned_new_array_called = 0;
175cc89063bSNico Weber         aligned_delete_array_called = 0;
176cc89063bSNico Weber         last_new_array_size = 0;
177cc89063bSNico Weber         last_new_array_align = 0;
178cc89063bSNico Weber     }
179cc89063bSNico Weber 
180cc89063bSNico Weber public:
181cc89063bSNico Weber     bool checkOutstandingNewEq(int n) const
182cc89063bSNico Weber     {
183cc89063bSNico Weber         return disable_checking || n == outstanding_new;
184cc89063bSNico Weber     }
185cc89063bSNico Weber 
186ca06c330SLouis Dionne     bool checkOutstandingNewLessThanOrEqual(int n) const
187ca06c330SLouis Dionne     {
188ca06c330SLouis Dionne         return disable_checking || outstanding_new <= n;
189ca06c330SLouis Dionne     }
190ca06c330SLouis Dionne 
191cc89063bSNico Weber     bool checkOutstandingNewNotEq(int n) const
192cc89063bSNico Weber     {
193cc89063bSNico Weber         return disable_checking || n != outstanding_new;
194cc89063bSNico Weber     }
195cc89063bSNico Weber 
196cc89063bSNico Weber     bool checkNewCalledEq(int n) const
197cc89063bSNico Weber     {
198cc89063bSNico Weber         return disable_checking || n == new_called;
199cc89063bSNico Weber     }
200cc89063bSNico Weber 
201cc89063bSNico Weber     bool checkNewCalledNotEq(int n) const
202cc89063bSNico Weber     {
203cc89063bSNico Weber         return disable_checking || n != new_called;
204cc89063bSNico Weber     }
205cc89063bSNico Weber 
206cc89063bSNico Weber     bool checkNewCalledGreaterThan(int n) const
207cc89063bSNico Weber     {
208cc89063bSNico Weber         return disable_checking || new_called > n;
209cc89063bSNico Weber     }
210cc89063bSNico Weber 
211cc89063bSNico Weber     bool checkDeleteCalledEq(int n) const
212cc89063bSNico Weber     {
213cc89063bSNico Weber         return disable_checking || n == delete_called;
214cc89063bSNico Weber     }
215cc89063bSNico Weber 
216cc89063bSNico Weber     bool checkDeleteCalledNotEq(int n) const
217cc89063bSNico Weber     {
218cc89063bSNico Weber         return disable_checking || n != delete_called;
219cc89063bSNico Weber     }
220cc89063bSNico Weber 
221243da90eSArthur O'Dwyer     bool checkDeleteCalledGreaterThan(int n) const
222243da90eSArthur O'Dwyer     {
223243da90eSArthur O'Dwyer         return disable_checking || delete_called > n;
224243da90eSArthur O'Dwyer     }
225243da90eSArthur O'Dwyer 
226cc89063bSNico Weber     bool checkAlignedNewCalledEq(int n) const
227cc89063bSNico Weber     {
228cc89063bSNico Weber         return disable_checking || n == aligned_new_called;
229cc89063bSNico Weber     }
230cc89063bSNico Weber 
231cc89063bSNico Weber     bool checkAlignedNewCalledNotEq(int n) const
232cc89063bSNico Weber     {
233cc89063bSNico Weber         return disable_checking || n != aligned_new_called;
234cc89063bSNico Weber     }
235cc89063bSNico Weber 
236cc89063bSNico Weber     bool checkAlignedNewCalledGreaterThan(int n) const
237cc89063bSNico Weber     {
238cc89063bSNico Weber         return disable_checking || aligned_new_called > n;
239cc89063bSNico Weber     }
240cc89063bSNico Weber 
241cc89063bSNico Weber     bool checkAlignedDeleteCalledEq(int n) const
242cc89063bSNico Weber     {
243cc89063bSNico Weber         return disable_checking || n == aligned_delete_called;
244cc89063bSNico Weber     }
245cc89063bSNico Weber 
246cc89063bSNico Weber     bool checkAlignedDeleteCalledNotEq(int n) const
247cc89063bSNico Weber     {
248cc89063bSNico Weber         return disable_checking || n != aligned_delete_called;
249cc89063bSNico Weber     }
250cc89063bSNico Weber 
251cc89063bSNico Weber     bool checkLastNewSizeEq(std::size_t n) const
252cc89063bSNico Weber     {
253cc89063bSNico Weber         return disable_checking || n == last_new_size;
254cc89063bSNico Weber     }
255cc89063bSNico Weber 
256cc89063bSNico Weber     bool checkLastNewSizeNotEq(std::size_t n) const
257cc89063bSNico Weber     {
258cc89063bSNico Weber         return disable_checking || n != last_new_size;
259cc89063bSNico Weber     }
260cc89063bSNico Weber 
261243da90eSArthur O'Dwyer     bool checkLastNewSizeGe(std::size_t n) const
262243da90eSArthur O'Dwyer     {
263243da90eSArthur O'Dwyer         return disable_checking || last_new_size >= n;
264243da90eSArthur O'Dwyer     }
265243da90eSArthur O'Dwyer 
266cc89063bSNico Weber     bool checkLastNewAlignEq(std::size_t n) const
267cc89063bSNico Weber     {
268cc89063bSNico Weber         return disable_checking || n == last_new_align;
269cc89063bSNico Weber     }
270cc89063bSNico Weber 
271cc89063bSNico Weber     bool checkLastNewAlignNotEq(std::size_t n) const
272cc89063bSNico Weber     {
273cc89063bSNico Weber         return disable_checking || n != last_new_align;
274cc89063bSNico Weber     }
275cc89063bSNico Weber 
276243da90eSArthur O'Dwyer     bool checkLastNewAlignGe(std::size_t n) const
277243da90eSArthur O'Dwyer     {
278243da90eSArthur O'Dwyer         return disable_checking || last_new_align >= n;
279243da90eSArthur O'Dwyer     }
280243da90eSArthur O'Dwyer 
281cc89063bSNico Weber     bool checkLastDeleteAlignEq(std::size_t n) const
282cc89063bSNico Weber     {
283cc89063bSNico Weber         return disable_checking || n == last_delete_align;
284cc89063bSNico Weber     }
285cc89063bSNico Weber 
286cc89063bSNico Weber     bool checkLastDeleteAlignNotEq(std::size_t n) const
287cc89063bSNico Weber     {
288cc89063bSNico Weber         return disable_checking || n != last_delete_align;
289cc89063bSNico Weber     }
290cc89063bSNico Weber 
291cc89063bSNico Weber     bool checkOutstandingArrayNewEq(int n) const
292cc89063bSNico Weber     {
293cc89063bSNico Weber         return disable_checking || n == outstanding_array_new;
294cc89063bSNico Weber     }
295cc89063bSNico Weber 
296cc89063bSNico Weber     bool checkOutstandingArrayNewNotEq(int n) const
297cc89063bSNico Weber     {
298cc89063bSNico Weber         return disable_checking || n != outstanding_array_new;
299cc89063bSNico Weber     }
300cc89063bSNico Weber 
301cc89063bSNico Weber     bool checkNewArrayCalledEq(int n) const
302cc89063bSNico Weber     {
303cc89063bSNico Weber         return disable_checking || n == new_array_called;
304cc89063bSNico Weber     }
305cc89063bSNico Weber 
306cc89063bSNico Weber     bool checkNewArrayCalledNotEq(int n) const
307cc89063bSNico Weber     {
308cc89063bSNico Weber         return disable_checking || n != new_array_called;
309cc89063bSNico Weber     }
310cc89063bSNico Weber 
311cc89063bSNico Weber     bool checkDeleteArrayCalledEq(int n) const
312cc89063bSNico Weber     {
313cc89063bSNico Weber         return disable_checking || n == delete_array_called;
314cc89063bSNico Weber     }
315cc89063bSNico Weber 
316cc89063bSNico Weber     bool checkDeleteArrayCalledNotEq(int n) const
317cc89063bSNico Weber     {
318cc89063bSNico Weber         return disable_checking || n != delete_array_called;
319cc89063bSNico Weber     }
320cc89063bSNico Weber 
321cc89063bSNico Weber     bool checkAlignedNewArrayCalledEq(int n) const
322cc89063bSNico Weber     {
323cc89063bSNico Weber         return disable_checking || n == aligned_new_array_called;
324cc89063bSNico Weber     }
325cc89063bSNico Weber 
326cc89063bSNico Weber     bool checkAlignedNewArrayCalledNotEq(int n) const
327cc89063bSNico Weber     {
328cc89063bSNico Weber         return disable_checking || n != aligned_new_array_called;
329cc89063bSNico Weber     }
330cc89063bSNico Weber 
331cc89063bSNico Weber     bool checkAlignedNewArrayCalledGreaterThan(int n) const
332cc89063bSNico Weber     {
333cc89063bSNico Weber         return disable_checking || aligned_new_array_called > n;
334cc89063bSNico Weber     }
335cc89063bSNico Weber 
336cc89063bSNico Weber     bool checkAlignedDeleteArrayCalledEq(int n) const
337cc89063bSNico Weber     {
338cc89063bSNico Weber         return disable_checking || n == aligned_delete_array_called;
339cc89063bSNico Weber     }
340cc89063bSNico Weber 
341cc89063bSNico Weber     bool checkAlignedDeleteArrayCalledNotEq(int n) const
342cc89063bSNico Weber     {
343cc89063bSNico Weber         return disable_checking || n != aligned_delete_array_called;
344cc89063bSNico Weber     }
345cc89063bSNico Weber 
346cc89063bSNico Weber     bool checkLastNewArraySizeEq(std::size_t n) const
347cc89063bSNico Weber     {
348cc89063bSNico Weber         return disable_checking || n == last_new_array_size;
349cc89063bSNico Weber     }
350cc89063bSNico Weber 
351cc89063bSNico Weber     bool checkLastNewArraySizeNotEq(std::size_t n) const
352cc89063bSNico Weber     {
353cc89063bSNico Weber         return disable_checking || n != last_new_array_size;
354cc89063bSNico Weber     }
355cc89063bSNico Weber 
356cc89063bSNico Weber     bool checkLastNewArrayAlignEq(std::size_t n) const
357cc89063bSNico Weber     {
358cc89063bSNico Weber         return disable_checking || n == last_new_array_align;
359cc89063bSNico Weber     }
360cc89063bSNico Weber 
361cc89063bSNico Weber     bool checkLastNewArrayAlignNotEq(std::size_t n) const
362cc89063bSNico Weber     {
363cc89063bSNico Weber         return disable_checking || n != last_new_array_align;
364cc89063bSNico Weber     }
365cc89063bSNico Weber };
366cc89063bSNico Weber 
367cc89063bSNico Weber #ifdef DISABLE_NEW_COUNT
368cc89063bSNico Weber   const bool MemCounter::disable_checking = true;
369cc89063bSNico Weber #else
370cc89063bSNico Weber   const bool MemCounter::disable_checking = false;
371cc89063bSNico Weber #endif
372cc89063bSNico Weber 
37314324fa4SNikolas Klauser TEST_DIAGNOSTIC_PUSH
37414324fa4SNikolas Klauser TEST_MSVC_DIAGNOSTIC_IGNORED(4640) // '%s' construction of local static object is not thread safe (/Zc:threadSafeInit-)
375cc89063bSNico Weber inline MemCounter* getGlobalMemCounter() {
376cc89063bSNico Weber   static MemCounter counter((MemCounter::MemCounterCtorArg_()));
377cc89063bSNico Weber   return &counter;
378cc89063bSNico Weber }
37914324fa4SNikolas Klauser TEST_DIAGNOSTIC_POP
380cc89063bSNico Weber 
381cc89063bSNico Weber MemCounter &globalMemCounter = *getGlobalMemCounter();
382cc89063bSNico Weber 
383cc89063bSNico Weber #ifndef DISABLE_NEW_COUNT
38431452655SLouis Dionne // operator new(size_t[, nothrow_t]) and operator delete(size_t[, nothrow_t])
38531452655SLouis Dionne void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc) {
386cc89063bSNico Weber   getGlobalMemCounter()->newCalled(s);
387037a0528SJake Egan   if (s == 0)
388037a0528SJake Egan     ++s;
38931452655SLouis Dionne   void* p = std::malloc(s);
39031452655SLouis Dionne   if (p == nullptr)
391cc89063bSNico Weber     detail::throw_bad_alloc_helper();
39231452655SLouis Dionne   return p;
393cc89063bSNico Weber }
394cc89063bSNico Weber 
39531452655SLouis Dionne void* operator new(std::size_t s, std::nothrow_t const&) TEST_NOEXCEPT {
39631452655SLouis Dionne #  ifdef TEST_HAS_NO_EXCEPTIONS
39731452655SLouis Dionne   getGlobalMemCounter()->newCalled(s);
39831452655SLouis Dionne #  else
39931452655SLouis Dionne   try {
40031452655SLouis Dionne     getGlobalMemCounter()->newCalled(s);
40131452655SLouis Dionne   } catch (std::bad_alloc const&) {
40231452655SLouis Dionne     return nullptr;
40331452655SLouis Dionne   }
40431452655SLouis Dionne #  endif
40531452655SLouis Dionne   return std::malloc(s);
40631452655SLouis Dionne }
40731452655SLouis Dionne 
40831452655SLouis Dionne void operator delete(void* p) TEST_NOEXCEPT {
409cc89063bSNico Weber   getGlobalMemCounter()->deleteCalled(p);
410cc89063bSNico Weber   std::free(p);
411cc89063bSNico Weber }
412cc89063bSNico Weber 
41331452655SLouis Dionne void operator delete(void* p, std::nothrow_t const&) TEST_NOEXCEPT {
41431452655SLouis Dionne   getGlobalMemCounter()->deleteCalled(p);
41531452655SLouis Dionne   std::free(p);
416cc89063bSNico Weber }
417cc89063bSNico Weber 
41831452655SLouis Dionne // operator new[](size_t[, nothrow_t]) and operator delete[](size_t[, nothrow_t])
41931452655SLouis Dionne void* operator new[](std::size_t s) TEST_THROW_SPEC(std::bad_alloc) {
42031452655SLouis Dionne   getGlobalMemCounter()->newArrayCalled(s);
421037a0528SJake Egan   if (s == 0)
422037a0528SJake Egan     s++;
42331452655SLouis Dionne   void* p = std::malloc(s);
42431452655SLouis Dionne   if (p == nullptr)
42531452655SLouis Dionne     detail::throw_bad_alloc_helper();
42631452655SLouis Dionne   return p;
42731452655SLouis Dionne }
42831452655SLouis Dionne 
42931452655SLouis Dionne void* operator new[](std::size_t s, std::nothrow_t const&) TEST_NOEXCEPT {
43031452655SLouis Dionne #  ifdef TEST_HAS_NO_EXCEPTIONS
43131452655SLouis Dionne   getGlobalMemCounter()->newArrayCalled(s);
43231452655SLouis Dionne #  else
43331452655SLouis Dionne   try {
43431452655SLouis Dionne     getGlobalMemCounter()->newArrayCalled(s);
43531452655SLouis Dionne   } catch (std::bad_alloc const&) {
43631452655SLouis Dionne     return nullptr;
43731452655SLouis Dionne   }
43831452655SLouis Dionne #  endif
43931452655SLouis Dionne   return std::malloc(s);
44031452655SLouis Dionne }
44131452655SLouis Dionne 
44231452655SLouis Dionne void operator delete[](void* p) TEST_NOEXCEPT {
443cc89063bSNico Weber   getGlobalMemCounter()->deleteArrayCalled(p);
44431452655SLouis Dionne   std::free(p);
44531452655SLouis Dionne }
44631452655SLouis Dionne 
44731452655SLouis Dionne void operator delete[](void* p, std::nothrow_t const&) TEST_NOEXCEPT {
44831452655SLouis Dionne   getGlobalMemCounter()->deleteArrayCalled(p);
44931452655SLouis Dionne   std::free(p);
450cc89063bSNico Weber }
451cc89063bSNico Weber 
452cc89063bSNico Weber #  ifndef TEST_HAS_NO_ALIGNED_ALLOCATION
45331452655SLouis Dionne #    if defined(_LIBCPP_MSVCRT_LIKE) || (!defined(_LIBCPP_VERSION) && defined(_WIN32))
454cc89063bSNico Weber #      define USE_ALIGNED_ALLOC
455cc89063bSNico Weber #    endif
456cc89063bSNico Weber 
457f71b6386SJoseph Huber #    if defined(__APPLE__)
458f71b6386SJoseph Huber #      if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) &&                                                   \
459f71b6386SJoseph Huber            __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500)
460f71b6386SJoseph Huber #        define TEST_HAS_NO_C11_ALIGNED_ALLOC
461f71b6386SJoseph Huber #      endif
462f71b6386SJoseph Huber #    elif defined(__ANDROID__) && __ANDROID_API__ < 28
463f71b6386SJoseph Huber #      define TEST_HAS_NO_C11_ALIGNED_ALLOC
464f71b6386SJoseph Huber #    endif
465f71b6386SJoseph Huber 
466b368404dSLouis Dionne inline void* allocate_aligned_impl(std::size_t size, std::align_val_t align) {
46731452655SLouis Dionne   const std::size_t alignment = static_cast<std::size_t>(align);
468b935ab8eSNikolas Klauser   void* ret                   = nullptr;
469cc89063bSNico Weber #    ifdef USE_ALIGNED_ALLOC
47031452655SLouis Dionne   ret = _aligned_malloc(size, alignment);
471f71b6386SJoseph Huber #    elif TEST_STD_VER >= 17 && !defined(TEST_HAS_NO_C11_ALIGNED_ALLOC)
472f71b6386SJoseph Huber   size_t rounded_size = (size + alignment - 1) & ~(alignment - 1);
473f71b6386SJoseph Huber   ret                 = aligned_alloc(alignment, size > rounded_size ? size : rounded_size);
474cc89063bSNico Weber #    else
47531452655SLouis Dionne   assert(posix_memalign(&ret, std::max(alignment, sizeof(void*)), size) != EINVAL);
476cc89063bSNico Weber #    endif
477cc89063bSNico Weber   return ret;
478cc89063bSNico Weber }
479cc89063bSNico Weber 
48031452655SLouis Dionne inline void free_aligned_impl(void* ptr, std::align_val_t) {
48131452655SLouis Dionne   if (ptr) {
482cc89063bSNico Weber #    ifdef USE_ALIGNED_ALLOC
48331452655SLouis Dionne     ::_aligned_free(ptr);
484cc89063bSNico Weber #    else
48531452655SLouis Dionne     ::free(ptr);
486cc89063bSNico Weber #    endif
487cc89063bSNico Weber   }
488cc89063bSNico Weber }
489cc89063bSNico Weber 
49031452655SLouis Dionne // operator new(size_t, align_val_t[, nothrow_t]) and operator delete(size_t, align_val_t[, nothrow_t])
49131452655SLouis Dionne void* operator new(std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
49231452655SLouis Dionne   getGlobalMemCounter()->alignedNewCalled(s, static_cast<std::size_t>(av));
493b368404dSLouis Dionne   void* p = allocate_aligned_impl(s, av);
49431452655SLouis Dionne   if (p == nullptr)
49531452655SLouis Dionne     detail::throw_bad_alloc_helper();
49631452655SLouis Dionne   return p;
49731452655SLouis Dionne }
49831452655SLouis Dionne 
49931452655SLouis Dionne void* operator new(std::size_t s, std::align_val_t av, std::nothrow_t const&) TEST_NOEXCEPT {
50031452655SLouis Dionne #    ifdef TEST_HAS_NO_EXCEPTIONS
50131452655SLouis Dionne   getGlobalMemCounter()->alignedNewCalled(s, static_cast<std::size_t>(av));
50231452655SLouis Dionne #    else
50331452655SLouis Dionne   try {
50431452655SLouis Dionne     getGlobalMemCounter()->alignedNewCalled(s, static_cast<std::size_t>(av));
50531452655SLouis Dionne   } catch (std::bad_alloc const&) {
50631452655SLouis Dionne     return nullptr;
50731452655SLouis Dionne   }
50831452655SLouis Dionne #    endif
509b368404dSLouis Dionne   return allocate_aligned_impl(s, av);
51031452655SLouis Dionne }
51131452655SLouis Dionne 
51231452655SLouis Dionne void operator delete(void* p, std::align_val_t av) TEST_NOEXCEPT {
51331452655SLouis Dionne   getGlobalMemCounter()->alignedDeleteCalled(p, static_cast<std::size_t>(av));
51431452655SLouis Dionne   free_aligned_impl(p, av);
51531452655SLouis Dionne }
51631452655SLouis Dionne 
51731452655SLouis Dionne void operator delete(void* p, std::align_val_t av, std::nothrow_t const&) TEST_NOEXCEPT {
51831452655SLouis Dionne   getGlobalMemCounter()->alignedDeleteCalled(p, static_cast<std::size_t>(av));
51931452655SLouis Dionne   free_aligned_impl(p, av);
52031452655SLouis Dionne }
52131452655SLouis Dionne 
52231452655SLouis Dionne // operator new[](size_t, align_val_t[, nothrow_t]) and operator delete[](size_t, align_val_t[, nothrow_t])
523cc89063bSNico Weber void* operator new[](std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
52431452655SLouis Dionne   getGlobalMemCounter()->alignedNewArrayCalled(s, static_cast<std::size_t>(av));
525b368404dSLouis Dionne   void* p = allocate_aligned_impl(s, av);
52631452655SLouis Dionne   if (p == nullptr)
52731452655SLouis Dionne     detail::throw_bad_alloc_helper();
52831452655SLouis Dionne   return p;
52931452655SLouis Dionne }
53031452655SLouis Dionne 
53131452655SLouis Dionne void* operator new[](std::size_t s, std::align_val_t av, std::nothrow_t const&) TEST_NOEXCEPT {
53231452655SLouis Dionne #    ifdef TEST_HAS_NO_EXCEPTIONS
53331452655SLouis Dionne   getGlobalMemCounter()->alignedNewArrayCalled(s, static_cast<std::size_t>(av));
53431452655SLouis Dionne #    else
53531452655SLouis Dionne   try {
53631452655SLouis Dionne     getGlobalMemCounter()->alignedNewArrayCalled(s, static_cast<std::size_t>(av));
53731452655SLouis Dionne   } catch (std::bad_alloc const&) {
53831452655SLouis Dionne     return nullptr;
53931452655SLouis Dionne   }
54031452655SLouis Dionne #    endif
541b368404dSLouis Dionne   return allocate_aligned_impl(s, av);
542cc89063bSNico Weber }
543cc89063bSNico Weber 
544cc89063bSNico Weber void operator delete[](void* p, std::align_val_t av) TEST_NOEXCEPT {
54531452655SLouis Dionne   getGlobalMemCounter()->alignedDeleteArrayCalled(p, static_cast<std::size_t>(av));
54631452655SLouis Dionne   free_aligned_impl(p, av);
54731452655SLouis Dionne }
54831452655SLouis Dionne 
54931452655SLouis Dionne void operator delete[](void* p, std::align_val_t av, std::nothrow_t const&) TEST_NOEXCEPT {
55031452655SLouis Dionne   getGlobalMemCounter()->alignedDeleteArrayCalled(p, static_cast<std::size_t>(av));
55131452655SLouis Dionne   free_aligned_impl(p, av);
552cc89063bSNico Weber }
553cc89063bSNico Weber 
554cc89063bSNico Weber #  endif // TEST_HAS_NO_ALIGNED_ALLOCATION
555cc89063bSNico Weber 
556cc89063bSNico Weber #endif // DISABLE_NEW_COUNT
557cc89063bSNico Weber 
558cc89063bSNico Weber struct DisableAllocationGuard {
559cc89063bSNico Weber     explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable)
560cc89063bSNico Weber     {
561cc89063bSNico Weber         // Don't re-disable if already disabled.
562cc89063bSNico Weber         if (globalMemCounter.disable_allocations == true) m_disabled = false;
563cc89063bSNico Weber         if (m_disabled) globalMemCounter.disableAllocations();
564cc89063bSNico Weber     }
565cc89063bSNico Weber 
566cc89063bSNico Weber     void release() {
567cc89063bSNico Weber         if (m_disabled) globalMemCounter.enableAllocations();
568cc89063bSNico Weber         m_disabled = false;
569cc89063bSNico Weber     }
570cc89063bSNico Weber 
571cc89063bSNico Weber     ~DisableAllocationGuard() {
572cc89063bSNico Weber         release();
573cc89063bSNico Weber     }
574cc89063bSNico Weber 
575cc89063bSNico Weber private:
576cc89063bSNico Weber     bool m_disabled;
577cc89063bSNico Weber 
578cc89063bSNico Weber     DisableAllocationGuard(DisableAllocationGuard const&);
579cc89063bSNico Weber     DisableAllocationGuard& operator=(DisableAllocationGuard const&);
580cc89063bSNico Weber };
581cc89063bSNico Weber 
58229378ab2SNikolas Klauser #if TEST_STD_VER >= 20
58329378ab2SNikolas Klauser 
58429378ab2SNikolas Klauser struct ConstexprDisableAllocationGuard {
58529378ab2SNikolas Klauser     TEST_CONSTEXPR_CXX14 explicit ConstexprDisableAllocationGuard(bool disable = true) : m_disabled(disable)
58629378ab2SNikolas Klauser     {
58729378ab2SNikolas Klauser         if (!TEST_IS_CONSTANT_EVALUATED) {
58829378ab2SNikolas Klauser             // Don't re-disable if already disabled.
58929378ab2SNikolas Klauser             if (globalMemCounter.disable_allocations == true) m_disabled = false;
59029378ab2SNikolas Klauser             if (m_disabled) globalMemCounter.disableAllocations();
59129378ab2SNikolas Klauser         } else {
59229378ab2SNikolas Klauser             m_disabled = false;
59329378ab2SNikolas Klauser         }
59429378ab2SNikolas Klauser     }
59529378ab2SNikolas Klauser 
59629378ab2SNikolas Klauser     TEST_CONSTEXPR_CXX14 void release() {
59729378ab2SNikolas Klauser         if (!TEST_IS_CONSTANT_EVALUATED) {
59829378ab2SNikolas Klauser             if (m_disabled) globalMemCounter.enableAllocations();
59929378ab2SNikolas Klauser             m_disabled = false;
60029378ab2SNikolas Klauser         }
60129378ab2SNikolas Klauser     }
60229378ab2SNikolas Klauser 
60329378ab2SNikolas Klauser     TEST_CONSTEXPR_CXX20 ~ConstexprDisableAllocationGuard() {
60429378ab2SNikolas Klauser         release();
60529378ab2SNikolas Klauser     }
60629378ab2SNikolas Klauser 
60729378ab2SNikolas Klauser private:
60829378ab2SNikolas Klauser     bool m_disabled;
60929378ab2SNikolas Klauser 
61029378ab2SNikolas Klauser     ConstexprDisableAllocationGuard(ConstexprDisableAllocationGuard const&);
61129378ab2SNikolas Klauser     ConstexprDisableAllocationGuard& operator=(ConstexprDisableAllocationGuard const&);
61229378ab2SNikolas Klauser };
61329378ab2SNikolas Klauser 
61429378ab2SNikolas Klauser #endif
61529378ab2SNikolas Klauser 
616cc89063bSNico Weber struct RequireAllocationGuard {
617cc89063bSNico Weber     explicit RequireAllocationGuard(std::size_t RequireAtLeast = 1)
618cc89063bSNico Weber             : m_req_alloc(RequireAtLeast),
619cc89063bSNico Weber               m_new_count_on_init(globalMemCounter.new_called),
620cc89063bSNico Weber               m_outstanding_new_on_init(globalMemCounter.outstanding_new),
621cc89063bSNico Weber               m_exactly(false)
622cc89063bSNico Weber     {
623cc89063bSNico Weber     }
624cc89063bSNico Weber 
625cc89063bSNico Weber     void requireAtLeast(std::size_t N) { m_req_alloc = N; m_exactly = false; }
626cc89063bSNico Weber     void requireExactly(std::size_t N) { m_req_alloc = N; m_exactly = true; }
627cc89063bSNico Weber 
628cc89063bSNico Weber     ~RequireAllocationGuard() {
629cc89063bSNico Weber         assert(globalMemCounter.checkOutstandingNewEq(static_cast<int>(m_outstanding_new_on_init)));
630cc89063bSNico Weber         std::size_t Expect = m_new_count_on_init + m_req_alloc;
631cc89063bSNico Weber         assert(globalMemCounter.checkNewCalledEq(static_cast<int>(Expect)) ||
632cc89063bSNico Weber                (!m_exactly && globalMemCounter.checkNewCalledGreaterThan(static_cast<int>(Expect))));
633cc89063bSNico Weber     }
634cc89063bSNico Weber 
635cc89063bSNico Weber private:
636cc89063bSNico Weber     std::size_t m_req_alloc;
637cc89063bSNico Weber     const std::size_t m_new_count_on_init;
638cc89063bSNico Weber     const std::size_t m_outstanding_new_on_init;
639cc89063bSNico Weber     bool m_exactly;
640cc89063bSNico Weber     RequireAllocationGuard(RequireAllocationGuard const&);
641cc89063bSNico Weber     RequireAllocationGuard& operator=(RequireAllocationGuard const&);
642cc89063bSNico Weber };
643cc89063bSNico Weber 
644cc89063bSNico Weber #endif /* COUNT_NEW_H */
645