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