[libcxx-commits] [libcxx] [libc++] Remove _LIBCPP_COMPRESSED_PAIR/TRIPLE from shared_ptr (PR #200401)

Nico Weber via libcxx-commits libcxx-commits at lists.llvm.org
Wed Sep 9 06:57:30 PDT 2026


================
@@ -128,79 +126,53 @@ class __shared_ptr_pointer : public __shared_weak_count {
 struct __for_overwrite_tag {};
 
 template <class _Tp, class _Alloc>
-struct __shared_ptr_emplace : __shared_weak_count {
-  using __value_type _LIBCPP_NODEBUG = __remove_cv_t<_Tp>;
+struct _LIBCPP_HIDE_STRUCT_FROM_ABI __shared_ptr_emplace : __shared_weak_count {
+  using __alloc_t _LIBCPP_NODEBUG      = __allocator_traits_rebind_t<_Alloc, __shared_ptr_emplace>;
+  using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<__alloc_t>;
+  using __value_type _LIBCPP_NODEBUG   = __remove_cv_t<_Tp>;
 
-  template <class... _Args,
-            class _Allocator                                                                         = _Alloc,
-            __enable_if_t<is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&...) : __storage_(std::move(__a)) {
-    static_assert(
-        sizeof...(_Args) == 0, "No argument should be provided to the control block when using _for_overwrite");
-    ::new (static_cast<void*>(__get_elem())) __value_type;
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&... __args) : __alloc_(std::move(__a)) {
+    __alloc_traits::construct(__alloc_, __get_elem(), std::forward<_Args>(__args)...);
   }
 
-  template <class... _Args,
-            class _Allocator                                                                          = _Alloc,
-            __enable_if_t<!is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&... __args) : __storage_(std::move(__a)) {
-    using _TpAlloc = typename __allocator_traits_rebind<_Alloc, __value_type>::type;
-    _TpAlloc __tmp(*__get_alloc());
-    allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), std::forward<_Args>(__args)...);
-  }
-
-  _LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT { return __storage_.__get_alloc(); }
-
-  _LIBCPP_HIDE_FROM_ABI __value_type* __get_elem() _NOEXCEPT { return __storage_.__get_elem(); }
+  _LIBCPP_HIDE_FROM_ABI __value_type* __get_elem() _NOEXCEPT { return reinterpret_cast<__value_type*>(__buffer_); }
 
 private:
-  template <class _Allocator                                                                         = _Alloc,
-            __enable_if_t<is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI void __on_zero_shared_impl() _NOEXCEPT {
-    __get_elem()->~__value_type();
-  }
-
-  template <class _Allocator                                                                          = _Alloc,
-            __enable_if_t<!is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI void __on_zero_shared_impl() _NOEXCEPT {
-    using _TpAlloc = typename __allocator_traits_rebind<_Allocator, __remove_cv_t<_Tp> >::type;
-    _TpAlloc __tmp(*__get_alloc());
-    allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem());
+  _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override {
+    __alloc_traits::destroy(__alloc_, __get_elem());
   }
 
-  _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { __on_zero_shared_impl(); }
-
   _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override {
-    using _ControlBlockAlloc   = typename __allocator_traits_rebind<_Alloc, __shared_ptr_emplace>::type;
-    using _ControlBlockPointer = typename allocator_traits<_ControlBlockAlloc>::pointer;
-    _ControlBlockAlloc __tmp(*__get_alloc());
-    __storage_.~_Storage();
-    allocator_traits<_ControlBlockAlloc>::deallocate(__tmp, pointer_traits<_ControlBlockPointer>::pointer_to(*this), 1);
+    __alloc_t __tmp(__alloc_);
+    __alloc_.~__alloc_t();
+    __alloc_traits::deallocate(__tmp, pointer_traits<typename __alloc_traits::pointer>::pointer_to(*this), 1);
   }
 
-  // TODO: It should be possible to refactor this to remove `_Storage` entirely.
-  // This class implements the control block for non-array shared pointers created
-  // through `std::allocate_shared` and `std::make_shared`.
-  struct _Storage {
-    struct _Data {
-      _LIBCPP_COMPRESSED_PAIR(_Alloc, __alloc_, __value_type, __elem_);
-    };
+  _LIBCPP_NO_UNIQUE_ADDRESS __alloc_t __alloc_;
+  _ALIGNAS_TYPE(__value_type) char __buffer_[sizeof(__value_type)];
+};
 
-    _ALIGNAS_TYPE(_Data) char __buffer_[sizeof(_Data)];
+template <class _Tp, class _Alloc>
+struct _LIBCPP_HIDE_STRUCT_FROM_ABI __shared_ptr_emplace_for_overwrite : __shared_weak_count {
+  using __alloc_t _LIBCPP_NODEBUG    = __allocator_traits_rebind_t<_Alloc, __shared_ptr_emplace_for_overwrite>;
+  using __value_type _LIBCPP_NODEBUG = __remove_cv_t<_Tp>;
 
-    _LIBCPP_HIDE_FROM_ABI explicit _Storage(_Alloc&& __a) { ::new ((void*)__get_alloc()) _Alloc(std::move(__a)); }
-    _LIBCPP_HIDE_FROM_ABI ~_Storage() { __get_alloc()->~_Alloc(); }
+  explicit __shared_ptr_emplace_for_overwrite(_Alloc __a) : __alloc_(std::move(__a)) {}
 
-    _LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT {
-      return std::addressof(reinterpret_cast<_Data*>(__buffer_)->__alloc_);
-    }
+  _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { __value_.~__value_type(); }
+  _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override {
+    __alloc_t __tmp(__alloc_);
+    __alloc_.~__alloc_t();
+    using __alloc_traits = allocator_traits<__alloc_t>;
+    __alloc_traits::deallocate(__tmp, pointer_traits<typename __alloc_traits::pointer>::pointer_to(*this), 1);
+  }
 
-    _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI __value_type* __get_elem() _NOEXCEPT {
----------------
nico wrote:

FWIW the _LIBCPP_NO_CFI removal here required us to add a CFI suppression for this function downstream. Consider re-adding it.

https://github.com/llvm/llvm-project/pull/200401


More information about the libcxx-commits mailing list