[libcxx-commits] [libcxx] [libc++] Add an ABI flag to make __bit_iterator trivially copyable (PR #172271)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Tue Dec 16 02:37:02 PST 2025


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

>From 3a42a0843a9243a079ac4de15df947cc7bebbbf8 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 15 Dec 2025 11:07:14 +0100
Subject: [PATCH] [libc++] Add an ABI flag to make __bit_iterator trivially
 copyable

---
 libcxx/docs/ABIGuarantees.rst                 |  4 +++
 libcxx/include/__bit_reference                | 11 +++++++-
 libcxx/include/__configuration/abi.h          |  1 +
 ...ll.pass.cpp => trivialty.compile.pass.cpp} | 26 +++++++------------
 4 files changed, 25 insertions(+), 17 deletions(-)
 rename libcxx/test/libcxx/containers/sequences/vector.bool/{trivial_for_purposes_of_call.pass.cpp => trivialty.compile.pass.cpp} (72%)

diff --git a/libcxx/docs/ABIGuarantees.rst b/libcxx/docs/ABIGuarantees.rst
index e680f5429880e..3b9b80991e50d 100644
--- a/libcxx/docs/ABIGuarantees.rst
+++ b/libcxx/docs/ABIGuarantees.rst
@@ -157,6 +157,10 @@ This flag adds ``[[clang::trivial_abi]]`` to ``unique_ptr``, which makes it triv
 ---------------------------------------------
 This flag adds ``[[clang::trivial_abi]]`` to ``shared_ptr``, which makes it trivial for the purpose of calls.
 
+``_LIBCPP_ABI_TRIVIALLY_COPYABLE_BIT_ITERATOR``
+-----------------------------------------------
+This flag makes ``__bit_iterator`` (a.k.a. ``vector<bool>::iterator``) trivially copyable as well as trivial for the
+purpose of calls, since the copy constructor is made trivial.
 
 Types that public aliases reference
 ===================================
diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference
index 00bbc4100ddb9..a21429b9ee3c3 100644
--- a/libcxx/include/__bit_reference
+++ b/libcxx/include/__bit_reference
@@ -314,10 +314,15 @@ public:
   // When _IsConst=true, this is a converting constructor;
   // the copy and move constructors are implicitly generated
   // and trivial.
+#ifdef _LIBCPP_ABI_TRIVIALLY_COPYABLE_BIT_ITERATOR
+  template <bool _IsConstDep = _IsConst, __enable_if_t<_IsConstDep, int> = 0>
+#endif
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator(const __bit_iterator<_Cp, false>& __it) _NOEXCEPT
       : __seg_(__it.__seg_),
-        __ctz_(__it.__ctz_) {}
+        __ctz_(__it.__ctz_) {
+  }
 
+#ifndef _LIBCPP_ABI_TRIVIALLY_COPYABLE_BIT_ITERATOR
   // When _IsConst=false, we have a user-provided copy constructor,
   // so we must also provide a copy assignment operator because
   // the implicit generation of a defaulted one is deprecated.
@@ -329,6 +334,10 @@ public:
     __ctz_ = __it.__ctz_;
     return *this;
   }
+#else
+  _LIBCPP_HIDE_FROM_ABI __bit_iterator(const __bit_iterator&)            = default;
+  _LIBCPP_HIDE_FROM_ABI __bit_iterator& operator=(const __bit_iterator&) = default;
+#endif // _LIBCPP_ABI_TRIVIALLY_COPYABLE_BIT_ITERATOR
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator*() const _NOEXCEPT {
     _LIBCPP_ASSERT_INTERNAL(__ctz_ < __bits_per_word, "Dereferencing an invalid __bit_iterator.");
diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h
index f30d0a5445b19..377710b55921b 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -84,6 +84,7 @@
 #  define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
 #  define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
 #  define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
+#  define _LIBCPP_ABI_TRIVIALLY_COPYABLE_BIT_ITERATOR
 
 #elif _LIBCPP_ABI_VERSION == 1
 #  if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
diff --git a/libcxx/test/libcxx/containers/sequences/vector.bool/trivial_for_purposes_of_call.pass.cpp b/libcxx/test/libcxx/containers/sequences/vector.bool/trivialty.compile.pass.cpp
similarity index 72%
rename from libcxx/test/libcxx/containers/sequences/vector.bool/trivial_for_purposes_of_call.pass.cpp
rename to libcxx/test/libcxx/containers/sequences/vector.bool/trivialty.compile.pass.cpp
index 4d37b83ba9cd6..41831da00d31f 100644
--- a/libcxx/test/libcxx/containers/sequences/vector.bool/trivial_for_purposes_of_call.pass.cpp
+++ b/libcxx/test/libcxx/containers/sequences/vector.bool/trivialty.compile.pass.cpp
@@ -38,19 +38,13 @@ using IsTrivialForCall = std::integral_constant<
     // Ignore the all-deleted case, it shouldn't occur here.
     >;
 
-void test_const_iterator() {
-  using It = std::vector<bool>::const_iterator;
-  static_assert(IsTrivialForCall<It>::value, "");
-}
-
-void test_non_const_iterator() {
-  using It = std::vector<bool>::iterator;
-  static_assert(!IsTrivialForCall<It>::value, "");
-}
-
-int main(int, char**) {
-  test_const_iterator();
-  test_non_const_iterator();
-
-  return 0;
-}
+static_assert(IsTrivialForCall<std::vector<bool>::const_iterator>::value, "");
+static_assert(std::is_trivially_copyable<std::vector<bool>::const_iterator>::value, "");
+
+#ifndef _LIBCPP_ABI_TRIVIALLY_COPYABLE_BIT_ITERATOR
+static_assert(!IsTrivialForCall<std::vector<bool>::iterator>::value, "");
+static_assert(!std::is_trivially_copyable<std::vector<bool>::iterator>::value, "");
+#else
+static_assert(IsTrivialForCall<std::vector<bool>::iterator>::value, "");
+static_assert(std::is_trivially_copyable<std::vector<bool>::iterator>::value, "");
+#endif



More information about the libcxx-commits mailing list