Quuxplusone created this revision. Quuxplusone added a reviewer: EricWF. Herald added subscribers: cfe-commits, JDevlieghere.
https://github.com/cplusplus/draft/commit/6216651aada9bc2f9cefe90edbde4ea9e32251ab `new_delete_resource().allocate(n, a)` has basically three permissible results: - Return an appropriately sized and aligned block. - Throw bad_alloc. - If `n == 0`, return an unspecified result. Before this patch, libc++'s `new_delete_resource` would do a fourth 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 `<memory_resource>`-specific workaround.) Repository: rCXX libc++ https://reviews.llvm.org/D47344 Files: src/experimental/memory_resource.cpp Index: src/experimental/memory_resource.cpp =================================================================== --- src/experimental/memory_resource.cpp +++ src/experimental/memory_resource.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "experimental/memory_resource" +#include "memory" #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER #include "atomic" @@ -23,18 +24,36 @@ // new_delete_resource() +#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION +static bool is_aligned_to(void *ptr, size_t align) +{ + void *p2 = ptr; + size_t space = 1; + void *result = _VSTD::align(align, 1, p2, space); + return (result == ptr); +} +#endif + 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 */} + { + void *result = _VSTD::__libcpp_allocate(__size, __align); +#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION + if (__size != 0 && !is_aligned_to(result, __align)) { + __throw_bad_alloc(); + } +#endif + return result; + } virtual void do_deallocate(void * __p, size_t, size_t __align) - { _VSTD::__libcpp_deallocate(__p, __align); /* FIXME */ } + { _VSTD::__libcpp_deallocate(__p, __align); } virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT { return &__other == this; }
Index: src/experimental/memory_resource.cpp =================================================================== --- src/experimental/memory_resource.cpp +++ src/experimental/memory_resource.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "experimental/memory_resource" +#include "memory" #ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER #include "atomic" @@ -23,18 +24,36 @@ // new_delete_resource() +#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION +static bool is_aligned_to(void *ptr, size_t align) +{ + void *p2 = ptr; + size_t space = 1; + void *result = _VSTD::align(align, 1, p2, space); + return (result == ptr); +} +#endif + 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 */} + { + void *result = _VSTD::__libcpp_allocate(__size, __align); +#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION + if (__size != 0 && !is_aligned_to(result, __align)) { + __throw_bad_alloc(); + } +#endif + return result; + } virtual void do_deallocate(void * __p, size_t, size_t __align) - { _VSTD::__libcpp_deallocate(__p, __align); /* FIXME */ } + { _VSTD::__libcpp_deallocate(__p, __align); } virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT { return &__other == this; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits