From 7ffcd984c4de54dea96049b9cb6a74c9e9b84c1e Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Sat, 9 Mar 2019 00:38:19 +0000 Subject: [PATCH] LWG 2843 "Unclear behavior of std::pmr::memory_resource::do_allocate()" Patch by Arthur O'Dwyer. Reviewed as https://reviews.llvm.org/D47344 new_delete_resource().allocate(n, a) has basically two permissible results: * Return an appropriately sized and aligned block. * Throw bad_alloc. Before this patch, libc++'s new_delete_resource would do a third and impermissible thing, which was to return an appropriately sized but inappropriately under-aligned block. This is now fixed. (This came up while I was stress-testing unsynchronized_pool_resource on my MacBook. If we can't trust the default resource to return appropriately aligned blocks, pretty much everything breaks. For similar reasons, I would strongly support just patching __libcpp_allocate directly, but I don't care to die on that hill, so I made this patch as a -specific workaround.) llvm-svn: 355763 --- libcxx/src/experimental/memory_resource.cpp | 26 ++++++++++++--------- libcxx/www/cxx2a_status.html | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/libcxx/src/experimental/memory_resource.cpp b/libcxx/src/experimental/memory_resource.cpp index 977ee2b56ee3..22bc12c10050 100644 --- a/libcxx/src/experimental/memory_resource.cpp +++ b/libcxx/src/experimental/memory_resource.cpp @@ -25,19 +25,23 @@ _LIBCPP_BEGIN_NAMESPACE_LFTS_PMR class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp : public memory_resource { -public: - ~__new_delete_memory_resource_imp() = default; - -protected: - virtual void* do_allocate(size_t __size, size_t __align) - { return _VSTD::__libcpp_allocate(__size, __align); /* FIXME */} - - virtual void do_deallocate(void* __p, size_t __n, size_t __align) { - _VSTD::__libcpp_deallocate(__p, __n, __align); /* FIXME */ + void *do_allocate(size_t size, size_t align) override { +#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION + if (__is_overaligned_for_new(align)) + __throw_bad_alloc(); +#endif + return _VSTD::__libcpp_allocate(size, align); } - virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT - { return &__other == this; } + void do_deallocate(void *p, size_t n, size_t align) override { + _VSTD::__libcpp_deallocate(p, n, align); + } + + bool do_is_equal(memory_resource const & other) const _NOEXCEPT override + { return &other == this; } + +public: + ~__new_delete_memory_resource_imp() override = default; }; // null_memory_resource() diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html index 67f1e2f81e7a..4489399ebba5 100644 --- a/libcxx/www/cxx2a_status.html +++ b/libcxx/www/cxx2a_status.html @@ -219,7 +219,7 @@ 2164What are the semantics of vector.emplace(vector.begin(), vector.back())?Jacksonville 2243istream::putback problemJacksonvilleComplete 2816resize_file has impossible postconditionJacksonvilleNothing to do - 2843Unclear behavior of std::pmr::memory_resource::do_allocate()Jacksonville + 2843Unclear behavior of std::pmr::memory_resource::do_allocate()JacksonvilleComplete 2849Why does !is_regular_file(from) cause copy_file to report a "file already exists" error?JacksonvilleNothing to do 2851std::filesystem enum classes are now underspecifiedJacksonvilleNothing to do 2946LWG 2758's resolution missed further correctionsJacksonvilleComplete