blob: e3111e7a58f44584758b1ea8a6fd4fdfe0cbd32e [file] [log] [blame]
Eric Fiselierfa1e5db2016-01-19 21:52:04 +00001//===----------------------------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000010#ifndef COUNT_NEW_HPP
11#define COUNT_NEW_HPP
12
13# include <cstdlib>
14# include <cassert>
15# include <new>
16
Eric Fiselierd24c4652016-06-14 21:31:42 +000017#include "test_macros.h"
Eric Fiseliera4449da2015-01-27 23:03:38 +000018
Eric Fiselier8c4dc322016-06-26 19:42:59 +000019#if defined(TEST_HAS_SANITIZERS)
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000020#define DISABLE_NEW_COUNT
21#endif
22
Eric Fiselier506f9d52016-06-22 03:46:32 +000023namespace detail
24{
Eric Fiselier8c4dc322016-06-26 19:42:59 +000025 TEST_NORETURN
Eric Fiselier506f9d52016-06-22 03:46:32 +000026 inline void throw_bad_alloc_helper() {
27#ifndef TEST_HAS_NO_EXCEPTIONS
28 throw std::bad_alloc();
29#else
30 std::abort();
31#endif
32 }
33}
34
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000035class MemCounter
36{
37public:
38 // Make MemCounter super hard to accidentally construct or copy.
39 class MemCounterCtorArg_ {};
Eric Fiselierf17cecb2015-02-10 15:17:46 +000040 explicit MemCounter(MemCounterCtorArg_) { reset(); }
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000041
42private:
43 MemCounter(MemCounter const &);
44 MemCounter & operator=(MemCounter const &);
45
46public:
47 // All checks return true when disable_checking is enabled.
48 static const bool disable_checking;
49
Eric Fiselier7175a072015-07-31 02:24:58 +000050 // Disallow any allocations from occurring. Useful for testing that
51 // code doesn't perform any allocations.
52 bool disable_allocations;
53
Eric Fiselier506f9d52016-06-22 03:46:32 +000054 // number of allocations to throw after. Default (unsigned)-1. If
55 // throw_after has the default value it will never be decremented.
56 static const unsigned never_throw_value = static_cast<unsigned>(-1);
57 unsigned throw_after;
58
Eric Fiselierf17cecb2015-02-10 15:17:46 +000059 int outstanding_new;
60 int new_called;
61 int delete_called;
Eric Fiseliera8312872018-03-22 04:42:56 +000062 int aligned_new_called;
63 int aligned_delete_called;
Stephan T. Lavavejae5809a2016-12-06 01:14:43 +000064 std::size_t last_new_size;
Eric Fiseliera8312872018-03-22 04:42:56 +000065 std::size_t last_new_align;
66 std::size_t last_delete_align;
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000067
Eric Fiselierf17cecb2015-02-10 15:17:46 +000068 int outstanding_array_new;
69 int new_array_called;
70 int delete_array_called;
Eric Fiseliera8312872018-03-22 04:42:56 +000071 int aligned_new_array_called;
72 int aligned_delete_array_called;
Stephan T. Lavavejae5809a2016-12-06 01:14:43 +000073 std::size_t last_new_array_size;
Eric Fiseliera8312872018-03-22 04:42:56 +000074 std::size_t last_new_array_align;
75 std::size_t last_delete_array_align;
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000076
77public:
78 void newCalled(std::size_t s)
79 {
Eric Fiselier7175a072015-07-31 02:24:58 +000080 assert(disable_allocations == false);
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000081 assert(s);
Eric Fiselier506f9d52016-06-22 03:46:32 +000082 if (throw_after == 0) {
83 throw_after = never_throw_value;
84 detail::throw_bad_alloc_helper();
85 } else if (throw_after != never_throw_value) {
86 --throw_after;
87 }
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000088 ++new_called;
89 ++outstanding_new;
90 last_new_size = s;
91 }
92
Eric Fiseliera8312872018-03-22 04:42:56 +000093 void alignedNewCalled(std::size_t s, std::size_t a) {
94 newCalled(s);
95 ++aligned_new_called;
96 last_new_align = a;
97 }
98
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000099 void deleteCalled(void * p)
100 {
101 assert(p);
102 --outstanding_new;
103 ++delete_called;
104 }
105
Eric Fiseliera8312872018-03-22 04:42:56 +0000106 void alignedDeleteCalled(void *p, std::size_t a) {
107 deleteCalled(p);
108 ++aligned_delete_called;
109 last_delete_align = a;
110 }
111
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000112 void newArrayCalled(std::size_t s)
113 {
Eric Fiselier7175a072015-07-31 02:24:58 +0000114 assert(disable_allocations == false);
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000115 assert(s);
Eric Fiselier506f9d52016-06-22 03:46:32 +0000116 if (throw_after == 0) {
117 throw_after = never_throw_value;
118 detail::throw_bad_alloc_helper();
119 } else {
120 // don't decrement throw_after here. newCalled will end up doing that.
121 }
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000122 ++outstanding_array_new;
123 ++new_array_called;
124 last_new_array_size = s;
125 }
126
Eric Fiseliera8312872018-03-22 04:42:56 +0000127 void alignedNewArrayCalled(std::size_t s, std::size_t a) {
128 newArrayCalled(s);
129 ++aligned_new_array_called;
130 last_new_array_align = a;
131 }
132
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000133 void deleteArrayCalled(void * p)
134 {
135 assert(p);
136 --outstanding_array_new;
137 ++delete_array_called;
138 }
139
Eric Fiseliera8312872018-03-22 04:42:56 +0000140 void alignedDeleteArrayCalled(void * p, std::size_t a) {
141 deleteArrayCalled(p);
142 ++aligned_delete_array_called;
143 last_delete_array_align = a;
144 }
145
Eric Fiselier7175a072015-07-31 02:24:58 +0000146 void disableAllocations()
147 {
148 disable_allocations = true;
149 }
150
151 void enableAllocations()
152 {
153 disable_allocations = false;
154 }
155
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000156 void reset()
157 {
Eric Fiselier7175a072015-07-31 02:24:58 +0000158 disable_allocations = false;
Eric Fiselier506f9d52016-06-22 03:46:32 +0000159 throw_after = never_throw_value;
Eric Fiselier7175a072015-07-31 02:24:58 +0000160
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000161 outstanding_new = 0;
162 new_called = 0;
163 delete_called = 0;
Eric Fiseliera8312872018-03-22 04:42:56 +0000164 aligned_new_called = 0;
165 aligned_delete_called = 0;
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000166 last_new_size = 0;
Eric Fiseliera8312872018-03-22 04:42:56 +0000167 last_new_align = 0;
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000168
169 outstanding_array_new = 0;
170 new_array_called = 0;
171 delete_array_called = 0;
Eric Fiseliera8312872018-03-22 04:42:56 +0000172 aligned_new_array_called = 0;
173 aligned_delete_array_called = 0;
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000174 last_new_array_size = 0;
Eric Fiseliera8312872018-03-22 04:42:56 +0000175 last_new_array_align = 0;
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000176 }
177
178public:
179 bool checkOutstandingNewEq(int n) const
180 {
181 return disable_checking || n == outstanding_new;
182 }
183
184 bool checkOutstandingNewNotEq(int n) const
185 {
186 return disable_checking || n != outstanding_new;
187 }
188
189 bool checkNewCalledEq(int n) const
190 {
191 return disable_checking || n == new_called;
192 }
193
194 bool checkNewCalledNotEq(int n) const
195 {
196 return disable_checking || n != new_called;
197 }
198
Eric Fiselier6e9a6942016-06-17 19:46:40 +0000199 bool checkNewCalledGreaterThan(int n) const
200 {
201 return disable_checking || new_called > n;
202 }
203
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000204 bool checkDeleteCalledEq(int n) const
205 {
206 return disable_checking || n == delete_called;
207 }
208
209 bool checkDeleteCalledNotEq(int n) const
210 {
211 return disable_checking || n != delete_called;
212 }
213
Eric Fiseliera8312872018-03-22 04:42:56 +0000214 bool checkAlignedNewCalledEq(int n) const
215 {
216 return disable_checking || n == aligned_new_called;
217 }
218
219 bool checkAlignedNewCalledNotEq(int n) const
220 {
221 return disable_checking || n != aligned_new_called;
222 }
223
224 bool checkAlignedNewCalledGreaterThan(int n) const
225 {
226 return disable_checking || aligned_new_called > n;
227 }
228
229 bool checkAlignedDeleteCalledEq(int n) const
230 {
231 return disable_checking || n == aligned_delete_called;
232 }
233
234 bool checkAlignedDeleteCalledNotEq(int n) const
235 {
236 return disable_checking || n != aligned_delete_called;
237 }
238
Stephan T. Lavavejae5809a2016-12-06 01:14:43 +0000239 bool checkLastNewSizeEq(std::size_t n) const
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000240 {
241 return disable_checking || n == last_new_size;
242 }
243
Stephan T. Lavavejae5809a2016-12-06 01:14:43 +0000244 bool checkLastNewSizeNotEq(std::size_t n) const
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000245 {
246 return disable_checking || n != last_new_size;
247 }
248
Eric Fiseliera8312872018-03-22 04:42:56 +0000249 bool checkLastNewAlignEq(std::size_t n) const
250 {
251 return disable_checking || n == last_new_align;
252 }
253
254 bool checkLastNewAlignNotEq(std::size_t n) const
255 {
256 return disable_checking || n != last_new_align;
257 }
258
259 bool checkLastDeleteAlignEq(std::size_t n) const
260 {
261 return disable_checking || n == last_delete_align;
262 }
263
264 bool checkLastDeleteAlignNotEq(std::size_t n) const
265 {
266 return disable_checking || n != last_delete_align;
267 }
268
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000269 bool checkOutstandingArrayNewEq(int n) const
270 {
271 return disable_checking || n == outstanding_array_new;
272 }
273
274 bool checkOutstandingArrayNewNotEq(int n) const
275 {
276 return disable_checking || n != outstanding_array_new;
277 }
278
279 bool checkNewArrayCalledEq(int n) const
280 {
281 return disable_checking || n == new_array_called;
282 }
283
284 bool checkNewArrayCalledNotEq(int n) const
285 {
286 return disable_checking || n != new_array_called;
287 }
288
289 bool checkDeleteArrayCalledEq(int n) const
290 {
291 return disable_checking || n == delete_array_called;
292 }
293
294 bool checkDeleteArrayCalledNotEq(int n) const
295 {
296 return disable_checking || n != delete_array_called;
297 }
298
Eric Fiseliera8312872018-03-22 04:42:56 +0000299 bool checkAlignedNewArrayCalledEq(int n) const
300 {
301 return disable_checking || n == aligned_new_array_called;
302 }
303
304 bool checkAlignedNewArrayCalledNotEq(int n) const
305 {
306 return disable_checking || n != aligned_new_array_called;
307 }
308
309 bool checkAlignedNewArrayCalledGreaterThan(int n) const
310 {
311 return disable_checking || aligned_new_array_called > n;
312 }
313
314 bool checkAlignedDeleteArrayCalledEq(int n) const
315 {
316 return disable_checking || n == aligned_delete_array_called;
317 }
318
319 bool checkAlignedDeleteArrayCalledNotEq(int n) const
320 {
321 return disable_checking || n != aligned_delete_array_called;
322 }
323
Stephan T. Lavavejae5809a2016-12-06 01:14:43 +0000324 bool checkLastNewArraySizeEq(std::size_t n) const
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000325 {
326 return disable_checking || n == last_new_array_size;
327 }
328
Stephan T. Lavavejae5809a2016-12-06 01:14:43 +0000329 bool checkLastNewArraySizeNotEq(std::size_t n) const
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000330 {
331 return disable_checking || n != last_new_array_size;
332 }
Eric Fiseliera8312872018-03-22 04:42:56 +0000333
334 bool checkLastNewArrayAlignEq(std::size_t n) const
335 {
336 return disable_checking || n == last_new_array_align;
337 }
338
339 bool checkLastNewArrayAlignNotEq(std::size_t n) const
340 {
341 return disable_checking || n != last_new_array_align;
342 }
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000343};
344
345#ifdef DISABLE_NEW_COUNT
346 const bool MemCounter::disable_checking = true;
347#else
348 const bool MemCounter::disable_checking = false;
349#endif
350
Eric Fiselier186b81a2017-06-21 21:42:50 +0000351inline MemCounter* getGlobalMemCounter() {
352 static MemCounter counter((MemCounter::MemCounterCtorArg_()));
353 return &counter;
354}
355
356MemCounter &globalMemCounter = *getGlobalMemCounter();
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000357
358#ifndef DISABLE_NEW_COUNT
Eric Fiseliere5bca2b2016-12-11 02:47:36 +0000359void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000360{
Eric Fiselier186b81a2017-06-21 21:42:50 +0000361 getGlobalMemCounter()->newCalled(s);
Eric Fiselier506f9d52016-06-22 03:46:32 +0000362 void* ret = std::malloc(s);
363 if (ret == nullptr)
364 detail::throw_bad_alloc_helper();
365 return ret;
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000366}
367
Eric Fiseliere5bca2b2016-12-11 02:47:36 +0000368void operator delete(void* p) TEST_NOEXCEPT
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000369{
Eric Fiselier186b81a2017-06-21 21:42:50 +0000370 getGlobalMemCounter()->deleteCalled(p);
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000371 std::free(p);
372}
373
Eric Fiseliere5bca2b2016-12-11 02:47:36 +0000374void* operator new[](std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000375{
Eric Fiselier186b81a2017-06-21 21:42:50 +0000376 getGlobalMemCounter()->newArrayCalled(s);
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000377 return operator new(s);
378}
379
Eric Fiseliere5bca2b2016-12-11 02:47:36 +0000380void operator delete[](void* p) TEST_NOEXCEPT
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000381{
Eric Fiselier186b81a2017-06-21 21:42:50 +0000382 getGlobalMemCounter()->deleteArrayCalled(p);
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000383 operator delete(p);
384}
385
Eric Fiseliera8312872018-03-22 04:42:56 +0000386#ifndef TEST_HAS_NO_ALIGNED_ALLOCATION
387#if defined(_LIBCPP_MSVCRT_LIKE) || \
388 (!defined(_LIBCPP_VERSION) && defined(_WIN32))
389#define USE_ALIGNED_ALLOC
390#endif
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000391
Eric Fiseliera8312872018-03-22 04:42:56 +0000392void* operator new(std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
393 const std::size_t a = static_cast<std::size_t>(av);
394 getGlobalMemCounter()->alignedNewCalled(s, a);
395 void *ret;
396#ifdef USE_ALIGNED_ALLOC
397 ret = _aligned_malloc(s, a);
398#else
399 posix_memalign(&ret, a, s);
400#endif
401 if (ret == nullptr)
402 detail::throw_bad_alloc_helper();
403 return ret;
404}
405
406void operator delete(void *p, std::align_val_t av) TEST_NOEXCEPT {
407 const std::size_t a = static_cast<std::size_t>(av);
408 getGlobalMemCounter()->alignedDeleteCalled(p, a);
409 if (p) {
410#ifdef USE_ALIGNED_ALLOC
411 ::_aligned_free(p);
412#else
413 ::free(p);
414#endif
415 }
416}
417
418void* operator new[](std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
419 const std::size_t a = static_cast<std::size_t>(av);
420 getGlobalMemCounter()->alignedNewArrayCalled(s, a);
421 return operator new(s, av);
422}
423
424void operator delete[](void *p, std::align_val_t av) TEST_NOEXCEPT {
425 const std::size_t a = static_cast<std::size_t>(av);
426 getGlobalMemCounter()->alignedDeleteArrayCalled(p, a);
427 return operator delete(p, av);
428}
429
430#endif // TEST_HAS_NO_ALIGNED_ALLOCATION
431
432#endif // DISABLE_NEW_COUNT
Eric Fiselier7175a072015-07-31 02:24:58 +0000433
434struct DisableAllocationGuard {
435 explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable)
436 {
437 // Don't re-disable if already disabled.
438 if (globalMemCounter.disable_allocations == true) m_disabled = false;
439 if (m_disabled) globalMemCounter.disableAllocations();
440 }
441
442 void release() {
443 if (m_disabled) globalMemCounter.enableAllocations();
444 m_disabled = false;
445 }
446
447 ~DisableAllocationGuard() {
448 release();
449 }
450
451private:
452 bool m_disabled;
453
454 DisableAllocationGuard(DisableAllocationGuard const&);
455 DisableAllocationGuard& operator=(DisableAllocationGuard const&);
456};
457
Eric Fiselier6e9a6942016-06-17 19:46:40 +0000458struct RequireAllocationGuard {
459 explicit RequireAllocationGuard(std::size_t RequireAtLeast = 1)
460 : m_req_alloc(RequireAtLeast),
461 m_new_count_on_init(globalMemCounter.new_called),
462 m_outstanding_new_on_init(globalMemCounter.outstanding_new),
463 m_exactly(false)
464 {
465 }
466
467 void requireAtLeast(std::size_t N) { m_req_alloc = N; m_exactly = false; }
468 void requireExactly(std::size_t N) { m_req_alloc = N; m_exactly = true; }
469
470 ~RequireAllocationGuard() {
Stephan T. Lavavejae5809a2016-12-06 01:14:43 +0000471 assert(globalMemCounter.checkOutstandingNewEq(static_cast<int>(m_outstanding_new_on_init)));
Eric Fiselier6e9a6942016-06-17 19:46:40 +0000472 std::size_t Expect = m_new_count_on_init + m_req_alloc;
Stephan T. Lavavejae5809a2016-12-06 01:14:43 +0000473 assert(globalMemCounter.checkNewCalledEq(static_cast<int>(Expect)) ||
474 (!m_exactly && globalMemCounter.checkNewCalledGreaterThan(static_cast<int>(Expect))));
Eric Fiselier6e9a6942016-06-17 19:46:40 +0000475 }
476
477private:
478 std::size_t m_req_alloc;
479 const std::size_t m_new_count_on_init;
480 const std::size_t m_outstanding_new_on_init;
481 bool m_exactly;
482 RequireAllocationGuard(RequireAllocationGuard const&);
483 RequireAllocationGuard& operator=(RequireAllocationGuard const&);
484};
485
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000486#endif /* COUNT_NEW_HPP */