[libcxx-commits] [PATCH] D62641: Support arrays in make_shared and allocate_shared (P0674R1)
Zoe Carver via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Feb 15 13:41:56 PST 2021
zoecarver marked 6 inline comments as done.
zoecarver added inline comments.
================
Comment at: libcxx/include/memory:2720
+_LIBCPP_HIDE_FROM_ABI
+void __shared_ptr_array_construct_elements(_Alloc const& __alloc, _ValueType *__first, size_t __n, _Args&& ...__args) {
+ using _ValueAlloc = typename __allocator_traits_rebind<_Alloc, _ValueType>::type;
----------------
Why not pass by value?
================
Comment at: libcxx/include/memory:2752
+ else
+ __shared_ptr_array_destroy_elements(__alloc, __first, __i + 1);
+ throw;
----------------
ldionne wrote:
> I haven't looked for that specifically, but can you confirm that you are testing these two code paths?
Yes, these two code paths are tested. See L324 where we use `struct D` to throw.
================
Comment at: libcxx/include/memory:2787
+ _CharAlloc __tmp(__alloc_);
+ allocator_traits<_CharAlloc>::deallocate(__tmp, reinterpret_cast<char*>(this), __get_size());
+ }
----------------
ldionne wrote:
> Don't we need to run the destructor of `__alloc_` here?
Yep. Added a regression test, too.
================
Comment at: libcxx/include/memory:2793
+ using _DataBlock = typename std::aligned_storage<sizeof(_Tp), alignof(_Tp)>::type;
+ _DataBlock __data_[0];
+};
----------------
ldionne wrote:
> Is this legal C++? I thought that was a compiler extension and arrays had to have at least one element?
Yes, you're right. Fixed. (Supprising that we didn't get a warning, though?)
================
Comment at: libcxx/include/memory:2803
+ _LIBCPP_HIDE_FROM_ABI
+ size_t __get_size() noexcept { return sizeof(__shared_ptr_array_bound); }
+
----------------
ldionne wrote:
> Since this is only used in a single place in the body of `__shared_ptr_array_bound`, I think we could just inline the function at its single point of use and remove it. WDYT?
Agreed. Same with `__get_count`.
================
Comment at: libcxx/include/memory:3552
+
+ size_t __size = __n * sizeof(_ElemT) + sizeof(_ControlBlock);
+ __allocation_guard<_CharAllocator> __guard(__a, __size);
----------------
ldionne wrote:
> I *think* this can cause us to under allocate, for example if there needs to be padding between `__count_` and `__data_`:
>
> ```
> [[no_unique_address]] _Alloc __alloc_;
> size_t __count_;
> // padding possible here - would that be counted in sizeof(_ControlBlock)?
> _DataBlock __data_[0];
> ```
>
> This concern is moot if I'm right about `_DataBlock __data_[0]` being an extension and if we change to `_DataBlock __data_[1]` instead.
Moot because I fixed `__data_[0 -> 1]`.
However, I thought this was the whole point of using a zero size array at the end of a struct? Otherwise, why not just make an empty struct. So, yes, that padding would be accounted for:
```
struct UnsizedTail {
int size;
alignas(8) char buf[0];
};
// UnsizedTail = {i32, [4 x i8 padding], [0 x i8]
static_assert(sizeof(UnsizedTail) == 8);
```
That being said... when would there be padding between `size_t` and an aligned storage member?
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D62641/new/
https://reviews.llvm.org/D62641
More information about the libcxx-commits
mailing list