diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_const_lvalue_pair.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_const_lvalue_pair.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_const_lvalue_pair.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_const_lvalue_pair.pass.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include "test_macros.h" #include "test_std_memory_resource.h" @@ -39,8 +38,8 @@ TestResource R; std::pmr::memory_resource* M = &R; std::pmr::polymorphic_allocator

A(M); - P* ptr = (P*)std::malloc(sizeof(P)); - P* ptr2 = (P*)std::malloc(sizeof(P)); + P* ptr = (P*)new char[sizeof(P)]; + P* ptr2 = (P*)new char[sizeof(P)]; // UNDER TEST // A.construct(ptr, p); @@ -55,9 +54,9 @@ checkConstructionEquiv(ptr->second, ptr2->second); A.destroy(ptr); - std::free(ptr); + delete[] ptr; A.destroy(ptr2); - std::free(ptr2); + delete[] ptr2; return tres && ures; } diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_values.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_values.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_values.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/construct_pair_values.pass.cpp @@ -39,8 +39,8 @@ TestResource R; std::pmr::memory_resource* M = &R; std::pmr::polymorphic_allocator

A(M); - P* ptr = (P*)std::malloc(sizeof(P)); - P* ptr2 = (P*)std::malloc(sizeof(P)); + P* ptr = (P*)new char[sizeof(P)]; + P* ptr2 = (P*)new char[sizeof(P)]; // UNDER TEST // A.construct(ptr, std::forward(t), std::forward(u)); @@ -56,8 +56,8 @@ A.destroy(ptr); A.destroy(ptr2); - std::free(ptr); - std::free(ptr2); + delete[] ptr; + delete[] ptr2; return tres && ures; } diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/resource.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/resource.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/resource.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/resource.pass.cpp @@ -33,11 +33,13 @@ A const a(mptr); assert(a.resource() == mptr); } +#ifdef _LIBCPP_VERSION { A const a(nullptr); assert(a.resource() == nullptr); assert(a.resource() == nullptr); } +#endif // _LIBCPP_VERSION { A const a; assert(a.resource() == std::pmr::get_default_resource()); diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/select_on_container_copy_construction.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/select_on_container_copy_construction.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/select_on_container_copy_construction.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/select_on_container_copy_construction.pass.cpp @@ -22,6 +22,24 @@ #include "test_macros.h" +#ifndef _LIBCPP_VERSION +namespace { + struct resource : std::pmr::memory_resource { + void* do_allocate(std::size_t, std::size_t) override { + abort(); + } + + void do_deallocate(void*, std::size_t, std::size_t) override { + abort(); + } + + bool do_is_equal(const std::pmr::memory_resource& that) const noexcept override { + return dynamic_cast(&that) != nullptr; + } + } a_resource; +} +#endif // !_LIBCPP_VERSION + int main(int, char**) { typedef std::pmr::polymorphic_allocator A; { @@ -39,12 +57,17 @@ { std::pmr::memory_resource* mptr = (std::pmr::memory_resource*)42; std::pmr::set_default_resource(mptr); - A const a(nullptr); - assert(a.resource() == nullptr); +#ifdef _LIBCPP_VERSION + std::pmr::memory_resource* mptr2 = nullptr; +#else + std::pmr::memory_resource* mptr2 = &a_resource; +#endif + A const a(mptr2); + assert(a.resource() == mptr2); A const other = a.select_on_container_copy_construction(); assert(other.resource() == std::pmr::get_default_resource()); assert(other.resource() == mptr); - assert(a.resource() == nullptr); + assert(a.resource() == mptr2); } return 0; diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_from_underaligned_buffer.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_from_underaligned_buffer.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_from_underaligned_buffer.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_from_underaligned_buffer.pass.cpp @@ -40,12 +40,21 @@ mono1.release(); // Test a size that is just big enough to fit in the buffer, - // but can't fit if it's aligned. + // but will not fit with alignment greater than 1. ret = r1.allocate(16, 1); +#ifdef _MSVC_STL_VERSION + // MSVC can't implement LWG-3120 until the next ABI break + // (see https://github.com/microsoft/STL/issues/1468). + ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkNewCalledEq(1)); + mono1.release(); + ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkDeleteCalledEq(1)); + globalMemCounter.reset(); +#else // ^^^ MSVCSTL / not MSVCSTL vvv assert(ret == buffer + 1); mono1.release(); + ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkNewCalledEq(0)); +#endif // ^^^ not MSVCSTL - assert(globalMemCounter.checkNewCalledEq(0)); ret = r1.allocate(16, 2); ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkNewCalledEq(1)); ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkLastNewSizeGe(16)); diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_with_initial_size.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_with_initial_size.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_with_initial_size.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_with_initial_size.pass.cpp @@ -35,7 +35,9 @@ } int main(int, char**) { +#ifdef _LIBCPP_VERSION test(1); +#endif test(8); test(10); test(100); diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/ctor_does_not_allocate.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/ctor_does_not_allocate.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/ctor_does_not_allocate.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/ctor_does_not_allocate.pass.cpp @@ -20,6 +20,14 @@ #include "count_new.h" +#if defined(_MSVC_STL_VERSION) && _ITERATOR_DEBUG_LEVEL == 2 +// MSVCSTL's pool resources use a vector internally, which allocates a tracking +// object when iterator debugging +constexpr int alloc_delta = 1; +#else +constexpr int alloc_delta = 0; +#endif + template void test() { // Constructing a pool resource should not cause allocations @@ -30,13 +38,13 @@ std::pmr::set_default_resource(std::pmr::new_delete_resource()); PoolResource r1; - assert(globalMemCounter.checkNewCalledEq(0)); + assert(globalMemCounter.checkNewCalledEq(alloc_delta)); PoolResource r2(std::pmr::pool_options{1024, 2048}); - assert(globalMemCounter.checkNewCalledEq(0)); + assert(globalMemCounter.checkNewCalledEq(2 * alloc_delta)); PoolResource r3(std::pmr::pool_options{1024, 2048}, std::pmr::new_delete_resource()); - assert(globalMemCounter.checkNewCalledEq(0)); + assert(globalMemCounter.checkNewCalledEq(3 * alloc_delta)); } int main(int, char**) { diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/sync_with_default_resource.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/sync_with_default_resource.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/sync_with_default_resource.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/sync_with_default_resource.pass.cpp @@ -20,6 +20,7 @@ int main(int, char**) { std::pmr::memory_resource* expected = std::pmr::null_memory_resource(); std::pmr::set_default_resource(expected); +#if !defined(_MSVC_STL_VERSION) || !defined(_DEBUG) { std::pmr::pool_options opts{0, 0}; std::pmr::synchronized_pool_resource r1; @@ -27,6 +28,7 @@ assert(r1.upstream_resource() == expected); assert(r2.upstream_resource() == expected); } +#endif // !defined(_MSVC_STL_VERSION) || !defined(_DEBUG) expected = std::pmr::new_delete_resource(); std::pmr::set_default_resource(expected); diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/unsync_with_default_resource.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/unsync_with_default_resource.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/unsync_with_default_resource.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.ctor/unsync_with_default_resource.pass.cpp @@ -20,6 +20,7 @@ int main(int, char**) { std::pmr::memory_resource* expected = std::pmr::null_memory_resource(); std::pmr::set_default_resource(expected); +#if !defined(_MSVC_STL_VERSION) || !defined(_DEBUG) { std::pmr::pool_options opts{0, 0}; std::pmr::unsynchronized_pool_resource r1; @@ -27,6 +28,7 @@ assert(r1.upstream_resource() == expected); assert(r2.upstream_resource() == expected); } +#endif // !defined(_MSVC_STL_VERSION) || !defined(_DEBUG) expected = std::pmr::new_delete_resource(); std::pmr::set_default_resource(expected); diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate.pass.cpp @@ -20,6 +20,14 @@ #include "count_new.h" #include "test_macros.h" +#if defined(_MSVC_STL_VERSION) && _ITERATOR_DEBUG_LEVEL == 2 +// MSVCSTL's pool resources use a vector internally, which allocates a tracking +// object when iterator debugging +constexpr int alloc_delta = 1; +#else +constexpr int alloc_delta = 0; +#endif + int main(int, char**) { globalMemCounter.reset(); { @@ -34,7 +42,7 @@ r1.deallocate(ret, 50); sync1.release(); ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkDeleteCalledGreaterThan(0)); - assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(globalMemCounter.checkOutstandingNewEq(alloc_delta)); globalMemCounter.reset(); @@ -46,7 +54,7 @@ // Check that the destructor calls release() } ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkDeleteCalledGreaterThan(0)); - assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(globalMemCounter.checkOutstandingNewEq(-alloc_delta)); return 0; } diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate_overaligned_request.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate_overaligned_request.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate_overaligned_request.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_allocate_overaligned_request.pass.cpp @@ -28,6 +28,14 @@ return (result == p); } +#if defined(_MSVC_STL_VERSION) && _ITERATOR_DEBUG_LEVEL == 2 +// MSVCSTL's pool resources use a vector internally, which allocates a tracking +// object when iterator debugging +constexpr int alloc_delta = 1; +#else +constexpr int alloc_delta = 0; +#endif + int main(int, char**) { globalMemCounter.reset(); std::pmr::pool_options opts{1, 1024}; @@ -37,7 +45,7 @@ constexpr size_t big_alignment = 8 * alignof(std::max_align_t); static_assert(big_alignment > 4); - assert(globalMemCounter.checkNewCalledEq(0)); + assert(globalMemCounter.checkNewCalledEq(alloc_delta)); void* ret = r1.allocate(2048, big_alignment); assert(ret != nullptr); diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_deallocate_matches_allocate.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_deallocate_matches_allocate.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_deallocate_matches_allocate.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_deallocate_matches_allocate.pass.cpp @@ -50,19 +50,30 @@ std::vector deallocations; }; +#if defined(_MSVC_STL_VERSION) && _ITERATOR_DEBUG_LEVEL == 2 +// MSVCSTL's pool resources use a vector internally, which allocates a tracking +// object when iterator debugging +constexpr int alloc_delta = 1; +#else +constexpr int alloc_delta = 0; +#endif + template void test_allocation_pattern(F do_pattern) { test_resource tr; - std::pmr::pool_options opts{0, 256}; - std::pmr::synchronized_pool_resource spr(opts, &tr); + { + std::pmr::pool_options opts{0, 256}; + std::pmr::synchronized_pool_resource spr(opts, &tr); + + try { + do_pattern(spr); + } catch (const std::bad_alloc&) { + } + spr.release(); - try { - do_pattern(spr); - } catch (const std::bad_alloc&) { + assert(tr.successful_allocations.size() == tr.deallocations.size() + alloc_delta); } - spr.release(); - assert(tr.successful_allocations.size() == tr.deallocations.size()); assert(std::is_permutation( tr.successful_allocations.begin(), tr.successful_allocations.end(), diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate.pass.cpp @@ -20,6 +20,14 @@ #include "count_new.h" #include "test_macros.h" +#if defined(_MSVC_STL_VERSION) && _ITERATOR_DEBUG_LEVEL == 2 +// MSVCSTL's pool resources use a vector internally, which allocates a tracking +// object when iterator debugging +constexpr int alloc_delta = 1; +#else +constexpr int alloc_delta = 0; +#endif + int main(int, char**) { globalMemCounter.reset(); { @@ -34,7 +42,7 @@ r1.deallocate(ret, 50); unsync1.release(); ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkDeleteCalledGreaterThan(0)); - assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(globalMemCounter.checkOutstandingNewEq(alloc_delta)); globalMemCounter.reset(); @@ -46,7 +54,7 @@ // Check that the destructor calls release() } ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkDeleteCalledGreaterThan(0)); - assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(globalMemCounter.checkOutstandingNewEq(-alloc_delta)); return 0; } diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate_overaligned_request.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate_overaligned_request.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate_overaligned_request.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_allocate_overaligned_request.pass.cpp @@ -28,6 +28,14 @@ return (result == p); } +#if defined(_MSVC_STL_VERSION) && _ITERATOR_DEBUG_LEVEL == 2 +// MSVCSTL's pool resources use a vector internally, which allocates a tracking +// object when iterator debugging +constexpr int alloc_delta = 1; +#else +constexpr int alloc_delta = 0; +#endif + int main(int, char**) { globalMemCounter.reset(); std::pmr::pool_options opts{1, 1024}; @@ -37,7 +45,7 @@ constexpr size_t big_alignment = 8 * alignof(std::max_align_t); static_assert(big_alignment > 4); - assert(globalMemCounter.checkNewCalledEq(0)); + assert(globalMemCounter.checkNewCalledEq(alloc_delta)); void* ret = r1.allocate(2048, big_alignment); assert(ret != nullptr); diff --git a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_deallocate_matches_allocate.pass.cpp b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_deallocate_matches_allocate.pass.cpp --- a/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_deallocate_matches_allocate.pass.cpp +++ b/libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/unsync_deallocate_matches_allocate.pass.cpp @@ -50,19 +50,30 @@ std::vector deallocations; }; +#if defined(_MSVC_STL_VERSION) && _ITERATOR_DEBUG_LEVEL == 2 +// MSVCSTL's pool resources use a vector internally, which allocates a tracking +// object when iterator debugging +constexpr int alloc_delta = 1; +#else +constexpr int alloc_delta = 0; +#endif + template void test_allocation_pattern(F do_pattern) { test_resource tr; - std::pmr::pool_options opts{0, 256}; - std::pmr::unsynchronized_pool_resource uspr(opts, &tr); + { + std::pmr::pool_options opts{0, 256}; + std::pmr::unsynchronized_pool_resource uspr(opts, &tr); + + try { + do_pattern(uspr); + } catch (const std::bad_alloc&) { + } + uspr.release(); - try { - do_pattern(uspr); - } catch (const std::bad_alloc&) { + assert(tr.successful_allocations.size() == tr.deallocations.size() + alloc_delta); } - uspr.release(); - assert(tr.successful_allocations.size() == tr.deallocations.size()); assert(std::is_permutation( tr.successful_allocations.begin(), tr.successful_allocations.end(),