blob: 8f66c5057d1abcd62453a48b2e8e7a32fd8c2f3a [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 Fiselierd24c4652016-06-14 21:31:42 +000019#if TEST_HAS_FEATURE(address_sanitizer) \
20 || TEST_HAS_FEATURE(memory_sanitizer) \
21 || TEST_HAS_FEATURE(thread_sanitizer)
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000022#define DISABLE_NEW_COUNT
23#endif
24
25class MemCounter
26{
27public:
28 // Make MemCounter super hard to accidentally construct or copy.
29 class MemCounterCtorArg_ {};
Eric Fiselierf17cecb2015-02-10 15:17:46 +000030 explicit MemCounter(MemCounterCtorArg_) { reset(); }
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000031
32private:
33 MemCounter(MemCounter const &);
34 MemCounter & operator=(MemCounter const &);
35
36public:
37 // All checks return true when disable_checking is enabled.
38 static const bool disable_checking;
39
Eric Fiselier7175a072015-07-31 02:24:58 +000040 // Disallow any allocations from occurring. Useful for testing that
41 // code doesn't perform any allocations.
42 bool disable_allocations;
43
Eric Fiselierf17cecb2015-02-10 15:17:46 +000044 int outstanding_new;
45 int new_called;
46 int delete_called;
47 int last_new_size;
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000048
Eric Fiselierf17cecb2015-02-10 15:17:46 +000049 int outstanding_array_new;
50 int new_array_called;
51 int delete_array_called;
52 int last_new_array_size;
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000053
54public:
55 void newCalled(std::size_t s)
56 {
Eric Fiselier7175a072015-07-31 02:24:58 +000057 assert(disable_allocations == false);
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000058 assert(s);
59 ++new_called;
60 ++outstanding_new;
61 last_new_size = s;
62 }
63
64 void deleteCalled(void * p)
65 {
66 assert(p);
67 --outstanding_new;
68 ++delete_called;
69 }
70
71 void newArrayCalled(std::size_t s)
72 {
Eric Fiselier7175a072015-07-31 02:24:58 +000073 assert(disable_allocations == false);
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000074 assert(s);
75 ++outstanding_array_new;
76 ++new_array_called;
77 last_new_array_size = s;
78 }
79
80 void deleteArrayCalled(void * p)
81 {
82 assert(p);
83 --outstanding_array_new;
84 ++delete_array_called;
85 }
86
Eric Fiselier7175a072015-07-31 02:24:58 +000087 void disableAllocations()
88 {
89 disable_allocations = true;
90 }
91
92 void enableAllocations()
93 {
94 disable_allocations = false;
95 }
96
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +000097 void reset()
98 {
Eric Fiselier7175a072015-07-31 02:24:58 +000099 disable_allocations = false;
100
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000101 outstanding_new = 0;
102 new_called = 0;
103 delete_called = 0;
104 last_new_size = 0;
105
106 outstanding_array_new = 0;
107 new_array_called = 0;
108 delete_array_called = 0;
109 last_new_array_size = 0;
110 }
111
112public:
113 bool checkOutstandingNewEq(int n) const
114 {
115 return disable_checking || n == outstanding_new;
116 }
117
118 bool checkOutstandingNewNotEq(int n) const
119 {
120 return disable_checking || n != outstanding_new;
121 }
122
123 bool checkNewCalledEq(int n) const
124 {
125 return disable_checking || n == new_called;
126 }
127
128 bool checkNewCalledNotEq(int n) const
129 {
130 return disable_checking || n != new_called;
131 }
132
133 bool checkDeleteCalledEq(int n) const
134 {
135 return disable_checking || n == delete_called;
136 }
137
138 bool checkDeleteCalledNotEq(int n) const
139 {
140 return disable_checking || n != delete_called;
141 }
142
143 bool checkLastNewSizeEq(int n) const
144 {
145 return disable_checking || n == last_new_size;
146 }
147
148 bool checkLastNewSizeNotEq(int n) const
149 {
150 return disable_checking || n != last_new_size;
151 }
152
153 bool checkOutstandingArrayNewEq(int n) const
154 {
155 return disable_checking || n == outstanding_array_new;
156 }
157
158 bool checkOutstandingArrayNewNotEq(int n) const
159 {
160 return disable_checking || n != outstanding_array_new;
161 }
162
163 bool checkNewArrayCalledEq(int n) const
164 {
165 return disable_checking || n == new_array_called;
166 }
167
168 bool checkNewArrayCalledNotEq(int n) const
169 {
170 return disable_checking || n != new_array_called;
171 }
172
173 bool checkDeleteArrayCalledEq(int n) const
174 {
175 return disable_checking || n == delete_array_called;
176 }
177
178 bool checkDeleteArrayCalledNotEq(int n) const
179 {
180 return disable_checking || n != delete_array_called;
181 }
182
183 bool checkLastNewArraySizeEq(int n) const
184 {
185 return disable_checking || n == last_new_array_size;
186 }
187
188 bool checkLastNewArraySizeNotEq(int n) const
189 {
190 return disable_checking || n != last_new_array_size;
191 }
192};
193
194#ifdef DISABLE_NEW_COUNT
195 const bool MemCounter::disable_checking = true;
196#else
197 const bool MemCounter::disable_checking = false;
198#endif
199
200MemCounter globalMemCounter((MemCounter::MemCounterCtorArg_()));
201
202#ifndef DISABLE_NEW_COUNT
203void* operator new(std::size_t s) throw(std::bad_alloc)
204{
205 globalMemCounter.newCalled(s);
206 return std::malloc(s);
207}
208
209void operator delete(void* p) throw()
210{
211 globalMemCounter.deleteCalled(p);
212 std::free(p);
213}
214
215
216void* operator new[](std::size_t s) throw(std::bad_alloc)
217{
218 globalMemCounter.newArrayCalled(s);
219 return operator new(s);
220}
221
222
223void operator delete[](void* p) throw()
224{
225 globalMemCounter.deleteArrayCalled(p);
226 operator delete(p);
227}
228
229#endif // DISABLE_NEW_COUNT
230
Eric Fiselier7175a072015-07-31 02:24:58 +0000231
232struct DisableAllocationGuard {
233 explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable)
234 {
235 // Don't re-disable if already disabled.
236 if (globalMemCounter.disable_allocations == true) m_disabled = false;
237 if (m_disabled) globalMemCounter.disableAllocations();
238 }
239
240 void release() {
241 if (m_disabled) globalMemCounter.enableAllocations();
242 m_disabled = false;
243 }
244
245 ~DisableAllocationGuard() {
246 release();
247 }
248
249private:
250 bool m_disabled;
251
252 DisableAllocationGuard(DisableAllocationGuard const&);
253 DisableAllocationGuard& operator=(DisableAllocationGuard const&);
254};
255
Eric Fiselier4eb5b6d2014-12-22 22:38:59 +0000256#endif /* COUNT_NEW_HPP */