[libcxx-commits] [libcxx] [libc++] Remove _LIBCPP_COMPRESSED_PAIR from packaged_task (PR #200642)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jun 26 03:15:08 PDT 2026


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/200642

>From 4a4a5854ea2ed1345f6e27d6a048248c92d8a3cf Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sun, 31 May 2026 09:59:17 +0200
Subject: [PATCH] [libc++] Remove _LIBCPP_COMPRESSED_PAIR from packaged_task

---
 libcxx/include/future                         | 11 ++--
 .../futures.task/destruction_order.pass.cpp   | 58 +++++++++++++++++++
 2 files changed, 64 insertions(+), 5 deletions(-)
 create mode 100644 libcxx/test/std/thread/futures/futures.task/destruction_order.pass.cpp

diff --git a/libcxx/include/future b/libcxx/include/future
index c169c6c182d83..30ceb97785811 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -379,7 +379,6 @@ template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>;
 #    include <__memory/allocator_arg_t.h>
 #    include <__memory/allocator_destructor.h>
 #    include <__memory/allocator_traits.h>
-#    include <__memory/compressed_pair.h>
 #    include <__memory/pointer_traits.h>
 #    include <__memory/shared_count.h>
 #    include <__memory/unique_ptr.h>
@@ -1413,8 +1412,10 @@ template <class _FD, class _Alloc, class _FB>
 class __packaged_task_func;
 
 template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
-class __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)> : public __packaged_task_base<_Rp(_ArgTypes...)> {
-  _LIBCPP_COMPRESSED_PAIR(_Fp, __func_, _Alloc, __alloc_);
+class _LIBCPP_HIDE_STRUCT_FROM_ABI
+    __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)> : public __packaged_task_base<_Rp(_ArgTypes...)> {
+  _LIBCPP_NO_UNIQUE_ADDRESS _Fp __func_;
+  _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_;
 
 public:
   _LIBCPP_HIDE_FROM_ABI explicit __packaged_task_func(const _Fp& __f) : __func_(__f) {}
@@ -1435,8 +1436,8 @@ void __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::__move_to(
 
 template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
 void __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy() {
-  __func_.~_Fp();
   __alloc_.~_Alloc();
+  __func_.~_Fp();
 }
 
 template <class _Fp, class _Alloc, class _Rp, class... _ArgTypes>
@@ -1445,8 +1446,8 @@ void __packaged_task_func<_Fp, _Alloc, _Rp(_ArgTypes...)>::destroy_deallocate()
   typedef allocator_traits<_Ap> _ATraits;
   typedef pointer_traits<typename _ATraits::pointer> _PTraits;
   _Ap __a(__alloc_);
-  __func_.~_Fp();
   __alloc_.~_Alloc();
+  __func_.~_Fp();
   __a.deallocate(_PTraits::pointer_to(*this), 1);
 }
 
diff --git a/libcxx/test/std/thread/futures/futures.task/destruction_order.pass.cpp b/libcxx/test/std/thread/futures/futures.task/destruction_order.pass.cpp
new file mode 100644
index 0000000000000..6a14f90d1d73b
--- /dev/null
+++ b/libcxx/test/std/thread/futures/futures.task/destruction_order.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: no-threads
+//
+// REQUIRES: c++03 || c++11 || c++14
+//
+// <future>
+//
+// Ensure that packaged_task destroys its members in the correct order.
+
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+#include <future>
+
+#include "test_macros.h"
+
+template <int Align, int BufferSize>
+struct alignas(Align) CallableWithPadding {
+  CallableWithPadding() {} // Allow putting object into the tail padding
+  CallableWithPadding(const CallableWithPadding&) {}
+  CallableWithPadding& operator=(const CallableWithPadding&) { return *this; }
+  ~CallableWithPadding() { std::memset(static_cast<void*>(this), 0, sizeof(*this)); }
+
+  void operator()() {}
+
+  char buffer[BufferSize];
+};
+
+template <class T>
+struct AllocatorWithData {
+  using value_type = T;
+
+  AllocatorWithData() : data(123) {}
+  AllocatorWithData(const AllocatorWithData& other) : data(other.data) {}
+  AllocatorWithData& operator=(const AllocatorWithData& other) { data = other.data; }
+  ~AllocatorWithData() { assert(data == 123); }
+
+  template <class U>
+  AllocatorWithData(const AllocatorWithData<U>& other) : data(other.data) {}
+
+  uint64_t data;
+
+  T* allocate(size_t n) { return std::allocator<T>().allocate(n); }
+  void deallocate(T* ptr, size_t n) { std::allocator<T>().deallocate(ptr, n); }
+};
+
+int main(int, char**) {
+  std::packaged_task<void()> heap(std::allocator_arg, AllocatorWithData<int>{}, CallableWithPadding<32, 24>{});
+  std::packaged_task<void()> stack(std::allocator_arg, AllocatorWithData<int>{}, CallableWithPadding<16, 8>{});
+  return 0;
+}



More information about the libcxx-commits mailing list