blob: 1b05fe35e948e873afdbb4a8014c87713be88f53 [file] [log] [blame]
Eric Fiselier38236b52016-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 Fiselier2cbc6542014-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 Fiselierf2f2a632016-06-14 21:31:42 +000017#include "test_macros.h"
Eric Fiselier5a4ee412015-01-27 23:03:38 +000018
Eric Fiselier37400712016-06-26 19:42:59 +000019#if defined(TEST_HAS_SANITIZERS)
Eric Fiselier2cbc6542014-12-22 22:38:59 +000020#define DISABLE_NEW_COUNT
21#endif
22
Eric Fiselier8ff74322016-06-22 03:46:32 +000023namespace detail
24{
Eric Fiselier37400712016-06-26 19:42:59 +000025 TEST_NORETURN
Eric Fiselier8ff74322016-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 Fiselier2cbc6542014-12-22 22:38:59 +000035class MemCounter
36{
37public:
38 // Make MemCounter super hard to accidentally construct or copy.
39 class MemCounterCtorArg_ {};
Eric Fiselier85b788c2015-02-10 15:17:46 +000040 explicit MemCounter(MemCounterCtorArg_) { reset(); }
Eric Fiselier2cbc6542014-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 Fiselier3461dbc2015-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 Fiselier8ff74322016-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 Fiselier85b788c2015-02-10 15:17:46 +000059 int outstanding_new;
60 int new_called;
61 int delete_called;
Stephan T. Lavavejf41847c2016-12-06 01:14:43 +000062 std::size_t last_new_size;
Eric Fiselier2cbc6542014-12-22 22:38:59 +000063
Eric Fiselier85b788c2015-02-10 15:17:46 +000064 int outstanding_array_new;
65 int new_array_called;
66 int delete_array_called;
Stephan T. Lavavejf41847c2016-12-06 01:14:43 +000067 std::size_t last_new_array_size;
Eric Fiselier2cbc6542014-12-22 22:38:59 +000068
69public:
70 void newCalled(std::size_t s)
71 {
Eric Fiselier3461dbc2015-07-31 02:24:58 +000072 assert(disable_allocations == false);
Eric Fiselier2cbc6542014-12-22 22:38:59 +000073 assert(s);
Eric Fiselier8ff74322016-06-22 03:46:32 +000074 if (throw_after == 0) {
75 throw_after = never_throw_value;
76 detail::throw_bad_alloc_helper();
77 } else if (throw_after != never_throw_value) {
78 --throw_after;
79 }
Eric Fiselier2cbc6542014-12-22 22:38:59 +000080 ++new_called;
81 ++outstanding_new;
82 last_new_size = s;
83 }
84
85 void deleteCalled(void * p)
86 {
87 assert(p);
88 --outstanding_new;
89 ++delete_called;
90 }
91
92 void newArrayCalled(std::size_t s)
93 {
Eric Fiselier3461dbc2015-07-31 02:24:58 +000094 assert(disable_allocations == false);
Eric Fiselier2cbc6542014-12-22 22:38:59 +000095 assert(s);
Eric Fiselier8ff74322016-06-22 03:46:32 +000096 if (throw_after == 0) {
97 throw_after = never_throw_value;
98 detail::throw_bad_alloc_helper();
99 } else {
100 // don't decrement throw_after here. newCalled will end up doing that.
101 }
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000102 ++outstanding_array_new;
103 ++new_array_called;
104 last_new_array_size = s;
105 }
106
107 void deleteArrayCalled(void * p)
108 {
109 assert(p);
110 --outstanding_array_new;
111 ++delete_array_called;
112 }
113
Eric Fiselier3461dbc2015-07-31 02:24:58 +0000114 void disableAllocations()
115 {
116 disable_allocations = true;
117 }
118
119 void enableAllocations()
120 {
121 disable_allocations = false;
122 }
123
Eric Fiselier8ff74322016-06-22 03:46:32 +0000124
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000125 void reset()
126 {
Eric Fiselier3461dbc2015-07-31 02:24:58 +0000127 disable_allocations = false;
Eric Fiselier8ff74322016-06-22 03:46:32 +0000128 throw_after = never_throw_value;
Eric Fiselier3461dbc2015-07-31 02:24:58 +0000129
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000130 outstanding_new = 0;
131 new_called = 0;
132 delete_called = 0;
133 last_new_size = 0;
134
135 outstanding_array_new = 0;
136 new_array_called = 0;
137 delete_array_called = 0;
138 last_new_array_size = 0;
139 }
140
141public:
142 bool checkOutstandingNewEq(int n) const
143 {
144 return disable_checking || n == outstanding_new;
145 }
146
147 bool checkOutstandingNewNotEq(int n) const
148 {
149 return disable_checking || n != outstanding_new;
150 }
151
152 bool checkNewCalledEq(int n) const
153 {
154 return disable_checking || n == new_called;
155 }
156
157 bool checkNewCalledNotEq(int n) const
158 {
159 return disable_checking || n != new_called;
160 }
161
Eric Fiselierc7979582016-06-17 19:46:40 +0000162 bool checkNewCalledGreaterThan(int n) const
163 {
164 return disable_checking || new_called > n;
165 }
166
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000167 bool checkDeleteCalledEq(int n) const
168 {
169 return disable_checking || n == delete_called;
170 }
171
172 bool checkDeleteCalledNotEq(int n) const
173 {
174 return disable_checking || n != delete_called;
175 }
176
Stephan T. Lavavejf41847c2016-12-06 01:14:43 +0000177 bool checkLastNewSizeEq(std::size_t n) const
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000178 {
179 return disable_checking || n == last_new_size;
180 }
181
Stephan T. Lavavejf41847c2016-12-06 01:14:43 +0000182 bool checkLastNewSizeNotEq(std::size_t n) const
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000183 {
184 return disable_checking || n != last_new_size;
185 }
186
187 bool checkOutstandingArrayNewEq(int n) const
188 {
189 return disable_checking || n == outstanding_array_new;
190 }
191
192 bool checkOutstandingArrayNewNotEq(int n) const
193 {
194 return disable_checking || n != outstanding_array_new;
195 }
196
197 bool checkNewArrayCalledEq(int n) const
198 {
199 return disable_checking || n == new_array_called;
200 }
201
202 bool checkNewArrayCalledNotEq(int n) const
203 {
204 return disable_checking || n != new_array_called;
205 }
206
207 bool checkDeleteArrayCalledEq(int n) const
208 {
209 return disable_checking || n == delete_array_called;
210 }
211
212 bool checkDeleteArrayCalledNotEq(int n) const
213 {
214 return disable_checking || n != delete_array_called;
215 }
216
Stephan T. Lavavejf41847c2016-12-06 01:14:43 +0000217 bool checkLastNewArraySizeEq(std::size_t n) const
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000218 {
219 return disable_checking || n == last_new_array_size;
220 }
221
Stephan T. Lavavejf41847c2016-12-06 01:14:43 +0000222 bool checkLastNewArraySizeNotEq(std::size_t n) const
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000223 {
224 return disable_checking || n != last_new_array_size;
225 }
226};
227
228#ifdef DISABLE_NEW_COUNT
229 const bool MemCounter::disable_checking = true;
230#else
231 const bool MemCounter::disable_checking = false;
232#endif
233
234MemCounter globalMemCounter((MemCounter::MemCounterCtorArg_()));
235
236#ifndef DISABLE_NEW_COUNT
Eric Fiselier3ca45662016-12-11 02:47:36 +0000237void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000238{
239 globalMemCounter.newCalled(s);
Eric Fiselier8ff74322016-06-22 03:46:32 +0000240 void* ret = std::malloc(s);
241 if (ret == nullptr)
242 detail::throw_bad_alloc_helper();
243 return ret;
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000244}
245
Eric Fiselier3ca45662016-12-11 02:47:36 +0000246void operator delete(void* p) TEST_NOEXCEPT
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000247{
248 globalMemCounter.deleteCalled(p);
249 std::free(p);
250}
251
252
Eric Fiselier3ca45662016-12-11 02:47:36 +0000253void* operator new[](std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000254{
255 globalMemCounter.newArrayCalled(s);
256 return operator new(s);
257}
258
259
Eric Fiselier3ca45662016-12-11 02:47:36 +0000260void operator delete[](void* p) TEST_NOEXCEPT
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000261{
262 globalMemCounter.deleteArrayCalled(p);
263 operator delete(p);
264}
265
266#endif // DISABLE_NEW_COUNT
267
Eric Fiselier3461dbc2015-07-31 02:24:58 +0000268
269struct DisableAllocationGuard {
270 explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable)
271 {
272 // Don't re-disable if already disabled.
273 if (globalMemCounter.disable_allocations == true) m_disabled = false;
274 if (m_disabled) globalMemCounter.disableAllocations();
275 }
276
277 void release() {
278 if (m_disabled) globalMemCounter.enableAllocations();
279 m_disabled = false;
280 }
281
282 ~DisableAllocationGuard() {
283 release();
284 }
285
286private:
287 bool m_disabled;
288
289 DisableAllocationGuard(DisableAllocationGuard const&);
290 DisableAllocationGuard& operator=(DisableAllocationGuard const&);
291};
292
Eric Fiselierc7979582016-06-17 19:46:40 +0000293
294struct RequireAllocationGuard {
295 explicit RequireAllocationGuard(std::size_t RequireAtLeast = 1)
296 : m_req_alloc(RequireAtLeast),
297 m_new_count_on_init(globalMemCounter.new_called),
298 m_outstanding_new_on_init(globalMemCounter.outstanding_new),
299 m_exactly(false)
300 {
301 }
302
303 void requireAtLeast(std::size_t N) { m_req_alloc = N; m_exactly = false; }
304 void requireExactly(std::size_t N) { m_req_alloc = N; m_exactly = true; }
305
306 ~RequireAllocationGuard() {
Stephan T. Lavavejf41847c2016-12-06 01:14:43 +0000307 assert(globalMemCounter.checkOutstandingNewEq(static_cast<int>(m_outstanding_new_on_init)));
Eric Fiselierc7979582016-06-17 19:46:40 +0000308 std::size_t Expect = m_new_count_on_init + m_req_alloc;
Stephan T. Lavavejf41847c2016-12-06 01:14:43 +0000309 assert(globalMemCounter.checkNewCalledEq(static_cast<int>(Expect)) ||
310 (!m_exactly && globalMemCounter.checkNewCalledGreaterThan(static_cast<int>(Expect))));
Eric Fiselierc7979582016-06-17 19:46:40 +0000311 }
312
313private:
314 std::size_t m_req_alloc;
315 const std::size_t m_new_count_on_init;
316 const std::size_t m_outstanding_new_on_init;
317 bool m_exactly;
318 RequireAllocationGuard(RequireAllocationGuard const&);
319 RequireAllocationGuard& operator=(RequireAllocationGuard const&);
320};
321
Eric Fiselier2cbc6542014-12-22 22:38:59 +0000322#endif /* COUNT_NEW_HPP */