[libcxx-commits] [libcxx] 1ba8ed0 - [libc++] Mark more types as trivially relocatable (#89724)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jun 17 04:09:08 PDT 2024


Author: Nikolas Klauser
Date: 2024-06-17T13:09:04+02:00
New Revision: 1ba8ed0cd7d03ed9b70aaf32b3d8e9205ef95ef2

URL: https://github.com/llvm/llvm-project/commit/1ba8ed0cd7d03ed9b70aaf32b3d8e9205ef95ef2
DIFF: https://github.com/llvm/llvm-project/commit/1ba8ed0cd7d03ed9b70aaf32b3d8e9205ef95ef2.diff

LOG: [libc++] Mark more types as trivially relocatable (#89724)

Co-authored-by: Louis Dionne <ldionne.2 at gmail.com>

Added: 
    

Modified: 
    libcxx/docs/ReleaseNotes/19.rst
    libcxx/include/__exception/exception_ptr.h
    libcxx/include/__expected/expected.h
    libcxx/include/__locale
    libcxx/include/__memory/shared_ptr.h
    libcxx/include/__split_buffer
    libcxx/include/__utility/pair.h
    libcxx/include/array
    libcxx/include/deque
    libcxx/include/optional
    libcxx/include/tuple
    libcxx/include/variant
    libcxx/include/vector
    libcxx/test/libcxx/transitive_includes/cxx03.csv
    libcxx/test/libcxx/transitive_includes/cxx11.csv
    libcxx/test/libcxx/transitive_includes/cxx14.csv
    libcxx/test/libcxx/transitive_includes/cxx17.csv
    libcxx/test/libcxx/transitive_includes/cxx20.csv
    libcxx/test/libcxx/transitive_includes/cxx23.csv
    libcxx/test/libcxx/transitive_includes/cxx26.csv
    libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index 6ab4cafd2bb76..71de10abb6eaa 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -58,6 +58,7 @@ Improvements and New Features
 -----------------------------
 
 - The performance of growing ``std::vector`` has been improved for trivially relocatable types.
+- A lot of types are considered trivially relocatable now, including ``vector`` and ``string``.
 - The performance of ``ranges::fill`` and ``ranges::fill_n`` has been improved for ``vector<bool>::iterator``\s,
   resulting in a performance increase of up to 1400x.
 - The ``std::mismatch`` algorithm has been optimized for integral types, which can lead up to 40x performance

diff  --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h
index 0a8337fa39de3..edb81caac0991 100644
--- a/libcxx/include/__exception/exception_ptr.h
+++ b/libcxx/include/__exception/exception_ptr.h
@@ -66,6 +66,9 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
   friend _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT;
 
 public:
+  // exception_ptr is basically a COW string.
+  using __trivially_relocatable = exception_ptr;
+
   _LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {}
   _LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}
 

diff  --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index d7adaac7567b2..0f994e297a877 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -31,6 +31,7 @@
 #include <__type_traits/is_swappable.h>
 #include <__type_traits/is_trivially_constructible.h>
 #include <__type_traits/is_trivially_destructible.h>
+#include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/is_void.h>
 #include <__type_traits/lazy.h>
 #include <__type_traits/negation.h>
@@ -463,6 +464,11 @@ class expected : private __expected_base<_Tp, _Err> {
   using error_type      = _Err;
   using unexpected_type = unexpected<_Err>;
 
+  using __trivially_relocatable =
+      __conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value && __libcpp_is_trivially_relocatable<_Err>::value,
+                      expected,
+                      void>;
+
   template <class _Up>
   using rebind = expected<_Up, error_type>;
 

diff  --git a/libcxx/include/__locale b/libcxx/include/__locale
index 1e97c7594c8bf..4b382764b4464 100644
--- a/libcxx/include/__locale
+++ b/libcxx/include/__locale
@@ -49,6 +49,9 @@ _LIBCPP_HIDE_FROM_ABI const _Facet& use_facet(const locale&);
 
 class _LIBCPP_EXPORTED_FROM_ABI locale {
 public:
+  // locale is essentially a shared_ptr that doesn't support weak_ptrs and never got a move constructor.
+  using __trivially_relocatable = locale;
+
   // types:
   class _LIBCPP_EXPORTED_FROM_ABI facet;
   class _LIBCPP_EXPORTED_FROM_ABI id;

diff  --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index a8ff189df2aa5..358a851958db1 100644
--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -419,6 +419,10 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr {
   typedef _Tp element_type;
 #endif
 
+  // A shared_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require
+  // any bookkeeping, so it's always trivially relocatable.
+  using __trivially_relocatable = shared_ptr;
+
 private:
   element_type* __ptr_;
   __shared_weak_count* __cntrl_;
@@ -1301,6 +1305,10 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr {
   typedef _Tp element_type;
 #endif
 
+  // A weak_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require
+  // any bookkeeping, so it's always trivially relocatable.
+  using __trivially_relocatable = weak_ptr;
+
 private:
   element_type* __ptr_;
   __shared_weak_count* __cntrl_;

diff  --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer
index c68349e0979c9..365a5fc4a2c6a 100644
--- a/libcxx/include/__split_buffer
+++ b/libcxx/include/__split_buffer
@@ -24,12 +24,14 @@
 #include <__memory/pointer_traits.h>
 #include <__memory/swap_allocator.h>
 #include <__type_traits/add_lvalue_reference.h>
+#include <__type_traits/conditional.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/integral_constant.h>
 #include <__type_traits/is_nothrow_assignable.h>
 #include <__type_traits/is_nothrow_constructible.h>
 #include <__type_traits/is_swappable.h>
 #include <__type_traits/is_trivially_destructible.h>
+#include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/remove_reference.h>
 #include <__utility/forward.h>
 #include <__utility/move.h>
@@ -64,6 +66,15 @@ public:
   using iterator        = pointer;
   using const_iterator  = const_pointer;
 
+  // A __split_buffer contains the following members which may be trivially relocatable:
+  // - pointer: may be trivially relocatable, so it's checked
+  // - allocator_type: may be trivially relocatable, so it's checked
+  // __split_buffer doesn't have any self-references, so it's trivially relocatable if its members are.
+  using __trivially_relocatable = __conditional_t<
+      __libcpp_is_trivially_relocatable<pointer>::value && __libcpp_is_trivially_relocatable<allocator_type>::value,
+      __split_buffer,
+      void>;
+
   pointer __first_;
   pointer __begin_;
   pointer __end_;

diff  --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h
index 3ffab2f7fe4f6..7e17c4c415c41 100644
--- a/libcxx/include/__utility/pair.h
+++ b/libcxx/include/__utility/pair.h
@@ -34,6 +34,7 @@
 #include <__type_traits/is_nothrow_constructible.h>
 #include <__type_traits/is_same.h>
 #include <__type_traits/is_swappable.h>
+#include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/nat.h>
 #include <__type_traits/remove_cvref.h>
 #include <__type_traits/unwrap_ref.h>
@@ -71,6 +72,11 @@ struct _LIBCPP_TEMPLATE_VIS pair
   _T1 first;
   _T2 second;
 
+  using __trivially_relocatable =
+      __conditional_t<__libcpp_is_trivially_relocatable<_T1>::value && __libcpp_is_trivially_relocatable<_T2>::value,
+                      pair,
+                      void>;
+
   _LIBCPP_HIDE_FROM_ABI pair(pair const&) = default;
   _LIBCPP_HIDE_FROM_ABI pair(pair&&)      = default;
 

diff  --git a/libcxx/include/array b/libcxx/include/array
index 6ea094deec32d..e030c6f32e9b2 100644
--- a/libcxx/include/array
+++ b/libcxx/include/array
@@ -130,6 +130,7 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce
 #include <__type_traits/is_nothrow_constructible.h>
 #include <__type_traits/is_same.h>
 #include <__type_traits/is_swappable.h>
+#include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/remove_cv.h>
 #include <__utility/empty.h>
 #include <__utility/integer_sequence.h>
@@ -166,6 +167,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp, size_t _Size>
 struct _LIBCPP_TEMPLATE_VIS array {
+  using __trivially_relocatable = __conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, array, void>;
+
   // types:
   using __self          = array;
   using value_type      = _Tp;

diff  --git a/libcxx/include/deque b/libcxx/include/deque
index 8ffd8193b74e9..051bb6551212e 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -477,6 +477,16 @@ public:
   using reverse_iterator       = std::reverse_iterator<iterator>;
   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
 
+  // A deque contains the following members which may be trivially relocatable:
+  // - __map: is a `__split_buffer`, see `__split_buffer` for more information on when it is trivially relocatable
+  // - size_type: is always trivially relocatable, since it is required to be an integral type
+  // - allocator_type: may not be trivially relocatable, so it's checked
+  // None of these are referencing the `deque` itself, so if all of them are trivially relocatable, `deque` is too.
+  using __trivially_relocatable = __conditional_t<
+      __libcpp_is_trivially_relocatable<__map>::value && __libcpp_is_trivially_relocatable<allocator_type>::value,
+      deque,
+      void>;
+
   static_assert(is_same<allocator_type, __rebind_alloc<__alloc_traits, value_type> >::value,
                 "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
                 "original allocator");

diff  --git a/libcxx/include/optional b/libcxx/include/optional
index 622e150f7a9f7..45e0987623f24 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -209,6 +209,7 @@ namespace std {
 #include <__type_traits/is_trivially_assignable.h>
 #include <__type_traits/is_trivially_constructible.h>
 #include <__type_traits/is_trivially_destructible.h>
+#include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/negation.h>
 #include <__type_traits/remove_const.h>
 #include <__type_traits/remove_cvref.h>
@@ -580,6 +581,8 @@ class _LIBCPP_DECLSPEC_EMPTY_BASES optional
 public:
   using value_type = _Tp;
 
+  using __trivially_relocatable = conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, optional, void>;
+
 private:
   // Disable the reference extension using this static assert.
   static_assert(!is_same_v<__remove_cvref_t<value_type>, in_place_t>,

diff  --git a/libcxx/include/tuple b/libcxx/include/tuple
index e7b43af7d13c0..e614e37cfaec6 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -240,6 +240,7 @@ template <class... Types>
 #include <__type_traits/is_reference.h>
 #include <__type_traits/is_same.h>
 #include <__type_traits/is_swappable.h>
+#include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/lazy.h>
 #include <__type_traits/maybe_const.h>
 #include <__type_traits/nat.h>
@@ -537,6 +538,8 @@ class _LIBCPP_TEMPLATE_VIS tuple {
   get(const tuple<_Up...>&&) _NOEXCEPT;
 
 public:
+  using __trivially_relocatable = __conditional_t<_And<__libcpp_is_trivially_relocatable<_Tp>...>::value, tuple, void>;
+
   // [tuple.cnstr]
 
   // tuple() constructors (including allocator_arg_t variants)

diff  --git a/libcxx/include/variant b/libcxx/include/variant
index 7ebd0534b1641..de451729768ba 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -241,6 +241,7 @@ namespace std {
 #include <__type_traits/is_trivially_assignable.h>
 #include <__type_traits/is_trivially_constructible.h>
 #include <__type_traits/is_trivially_destructible.h>
+#include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/is_void.h>
 #include <__type_traits/remove_const.h>
 #include <__type_traits/remove_cvref.h>
@@ -1180,6 +1181,9 @@ class _LIBCPP_TEMPLATE_VIS _LIBCPP_DECLSPEC_EMPTY_BASES variant
   using __first_type = variant_alternative_t<0, variant>;
 
 public:
+  using __trivially_relocatable =
+      conditional_t<_And<__libcpp_is_trivially_relocatable<_Types>...>::value, variant, void>;
+
   template <bool _Dummy                                                                               = true,
             enable_if_t<__dependent_type<is_default_constructible<__first_type>, _Dummy>::value, int> = 0>
   _LIBCPP_HIDE_FROM_ABI constexpr variant() noexcept(is_nothrow_default_constructible_v<__first_type>)

diff  --git a/libcxx/include/vector b/libcxx/include/vector
index cbfc2cefa1fd9..fb03f77dbe767 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -406,6 +406,15 @@ public:
   typedef std::reverse_iterator<iterator> reverse_iterator;
   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
 
+  // A vector containers the following members which may be trivially relocatable:
+  // - pointer: may be trivially relocatable, so it's checked
+  // - allocator_type: may be trivially relocatable, so it's checked
+  // vector doesn't contain any self-references, so it's trivially relocatable if its members are.
+  using __trivially_relocatable = __conditional_t<
+      __libcpp_is_trivially_relocatable<pointer>::value && __libcpp_is_trivially_relocatable<allocator_type>::value,
+      vector,
+      void>;
+
   static_assert((is_same<typename allocator_type::value_type, value_type>::value),
                 "Allocator::value_type must be same type as value_type");
 

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index b0431d9b2b551..c720a0c9a05ec 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -903,6 +903,7 @@ thread type_traits
 thread version
 tuple compare
 tuple cstddef
+tuple cstdint
 tuple exception
 tuple iosfwd
 tuple new

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index 6fc8fe5858c0d..b00436a1be7f7 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -910,6 +910,7 @@ thread type_traits
 thread version
 tuple compare
 tuple cstddef
+tuple cstdint
 tuple exception
 tuple iosfwd
 tuple new

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index 5771e2ba0761c..4b8c12929de0d 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -913,6 +913,7 @@ thread type_traits
 thread version
 tuple compare
 tuple cstddef
+tuple cstdint
 tuple exception
 tuple iosfwd
 tuple new

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index deba8c03d2f69..a51a7e2de1d38 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -914,6 +914,7 @@ thread type_traits
 thread version
 tuple compare
 tuple cstddef
+tuple cstdint
 tuple exception
 tuple iosfwd
 tuple new

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index b76ec5cf19900..5280d75cbf2e1 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -920,6 +920,7 @@ thread type_traits
 thread version
 tuple compare
 tuple cstddef
+tuple cstdint
 tuple exception
 tuple iosfwd
 tuple new

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index bd0ba126d4071..bfb8b5def6224 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -151,6 +151,7 @@ exception typeinfo
 exception version
 execution version
 expected cstddef
+expected cstdint
 expected initializer_list
 expected new
 expected version
@@ -484,6 +485,7 @@ regex typeinfo
 regex vector
 regex version
 scoped_allocator cstddef
+scoped_allocator cstdint
 scoped_allocator limits
 scoped_allocator new
 scoped_allocator tuple
@@ -640,6 +642,7 @@ thread typeinfo
 thread version
 tuple compare
 tuple cstddef
+tuple cstdint
 tuple version
 type_traits cstddef
 type_traits cstdint
@@ -674,6 +677,7 @@ unordered_set tuple
 unordered_set version
 utility compare
 utility cstddef
+utility cstdint
 utility initializer_list
 utility limits
 utility version

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index bd0ba126d4071..bfb8b5def6224 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -151,6 +151,7 @@ exception typeinfo
 exception version
 execution version
 expected cstddef
+expected cstdint
 expected initializer_list
 expected new
 expected version
@@ -484,6 +485,7 @@ regex typeinfo
 regex vector
 regex version
 scoped_allocator cstddef
+scoped_allocator cstdint
 scoped_allocator limits
 scoped_allocator new
 scoped_allocator tuple
@@ -640,6 +642,7 @@ thread typeinfo
 thread version
 tuple compare
 tuple cstddef
+tuple cstdint
 tuple version
 type_traits cstddef
 type_traits cstdint
@@ -674,6 +677,7 @@ unordered_set tuple
 unordered_set version
 utility compare
 utility cstddef
+utility cstdint
 utility initializer_list
 utility limits
 utility version

diff  --git a/libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp b/libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp
index 4d1a8ad9e229a..64d2c54e7dd84 100644
--- a/libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp
+++ b/libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp
@@ -7,11 +7,24 @@
 //===----------------------------------------------------------------------===//
 
 #include <__type_traits/is_trivially_relocatable.h>
+#include <array>
+#include <deque>
+#include <exception>
+#include <expected>
 #include <memory>
+#include <optional>
 #include <string>
+#include <tuple>
+#include <variant>
+#include <vector>
 
 #include "constexpr_char_traits.h"
 #include "test_allocator.h"
+#include "test_macros.h"
+
+#ifndef TEST_HAS_NO_LOCALIZATION
+#  include <locale>
+#endif
 
 static_assert(std::__libcpp_is_trivially_relocatable<char>::value, "");
 static_assert(std::__libcpp_is_trivially_relocatable<int>::value, "");
@@ -44,9 +57,27 @@ static_assert(std::__libcpp_is_trivially_relocatable<MoveOnlyTriviallyCopyable>:
 #else
 static_assert(!std::__libcpp_is_trivially_relocatable<MoveOnlyTriviallyCopyable>::value, "");
 #endif
+
+// library-internal types
+// ----------------------
+
+// __split_buffer
+static_assert(std::__libcpp_is_trivially_relocatable<std::__split_buffer<int> >::value, "");
+static_assert(std::__libcpp_is_trivially_relocatable<std::__split_buffer<NotTriviallyCopyable> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::__split_buffer<int, test_allocator<int> > >::value, "");
+
 // standard library types
 // ----------------------
 
+// array
+static_assert(std::__libcpp_is_trivially_relocatable<std::array<int, 0> >::value, "");
+static_assert(std::__libcpp_is_trivially_relocatable<std::array<NotTriviallyCopyable, 0> >::value, "");
+static_assert(std::__libcpp_is_trivially_relocatable<std::array<std::unique_ptr<int>, 0> >::value, "");
+
+static_assert(std::__libcpp_is_trivially_relocatable<std::array<int, 1> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::array<NotTriviallyCopyable, 1> >::value, "");
+static_assert(std::__libcpp_is_trivially_relocatable<std::array<std::unique_ptr<int>, 1> >::value, "");
+
 // basic_string
 #if defined(_LIBCPP_HAS_NO_ASAN) || !defined(_LIBCPP_INSTRUMENTED_WITH_ASAN)
 struct MyChar {
@@ -80,6 +111,71 @@ static_assert(
         std::basic_string<MyChar, NotTriviallyRelocatableCharTraits<MyChar>, test_allocator<MyChar> > >::value,
     "");
 #endif
+
+// deque
+static_assert(std::__libcpp_is_trivially_relocatable<std::deque<int> >::value, "");
+static_assert(std::__libcpp_is_trivially_relocatable<std::deque<NotTriviallyCopyable> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::deque<int, test_allocator<int> > >::value, "");
+
+// exception_ptr
+#ifndef _LIBCPP_ABI_MICROSOFT // FIXME: Is this also the case on windows?
+static_assert(std::__libcpp_is_trivially_relocatable<std::exception_ptr>::value, "");
+#endif
+
+// expected
+#if TEST_STD_VER >= 23
+static_assert(std::__libcpp_is_trivially_relocatable<std::expected<int, int> >::value);
+static_assert(std::__libcpp_is_trivially_relocatable<std::expected<std::unique_ptr<int>, int>>::value);
+static_assert(std::__libcpp_is_trivially_relocatable<std::expected<int, std::unique_ptr<int>>>::value);
+static_assert(std::__libcpp_is_trivially_relocatable<std::expected<std::unique_ptr<int>, std::unique_ptr<int>>>::value);
+
+static_assert(!std::__libcpp_is_trivially_relocatable<std::expected<int, NotTriviallyCopyable>>::value);
+static_assert(!std::__libcpp_is_trivially_relocatable<std::expected<NotTriviallyCopyable, int>>::value);
+static_assert(
+    !std::__libcpp_is_trivially_relocatable<std::expected<NotTriviallyCopyable, NotTriviallyCopyable>>::value);
+#endif
+
+// locale
+#ifndef TEST_HAS_NO_LOCALIZATION
+static_assert(std::__libcpp_is_trivially_relocatable<std::locale>::value, "");
+#endif
+
+// optional
+#if TEST_STD_VER >= 17
+static_assert(std::__libcpp_is_trivially_relocatable<std::optional<int>>::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::optional<NotTriviallyCopyable>>::value, "");
+static_assert(std::__libcpp_is_trivially_relocatable<std::optional<std::unique_ptr<int>>>::value, "");
+#endif // TEST_STD_VER >= 17
+
+// pair
+static_assert(std::__libcpp_is_trivially_relocatable<std::pair<int, int> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::pair<NotTriviallyCopyable, int> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::pair<int, NotTriviallyCopyable> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::pair<NotTriviallyCopyable, NotTriviallyCopyable> >::value,
+              "");
+static_assert(std::__libcpp_is_trivially_relocatable<std::pair<std::unique_ptr<int>, std::unique_ptr<int> > >::value,
+              "");
+
+// shared_ptr
+static_assert(std::__libcpp_is_trivially_relocatable<std::shared_ptr<NotTriviallyCopyable> >::value, "");
+
+// tuple
+#if TEST_STD_VER >= 11
+static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<> >::value, "");
+
+static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<int> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::tuple<NotTriviallyCopyable> >::value, "");
+static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<std::unique_ptr<int> > >::value, "");
+
+static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<int, int> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::tuple<NotTriviallyCopyable, int> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::tuple<int, NotTriviallyCopyable> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::tuple<NotTriviallyCopyable, NotTriviallyCopyable> >::value,
+              "");
+static_assert(std::__libcpp_is_trivially_relocatable<std::tuple<std::unique_ptr<int>, std::unique_ptr<int> > >::value,
+              "");
+#endif // TEST_STD_VER >= 11
+
 // unique_ptr
 struct NotTriviallyRelocatableDeleter {
   NotTriviallyRelocatableDeleter(const NotTriviallyRelocatableDeleter&);
@@ -113,4 +209,27 @@ static_assert(!std::__libcpp_is_trivially_relocatable<std::unique_ptr<int, NotTr
 static_assert(!std::__libcpp_is_trivially_relocatable<std::unique_ptr<int[], NotTriviallyRelocatablePointer> >::value,
               "");
 
+// variant
+#if TEST_STD_VER >= 17
+static_assert(std::__libcpp_is_trivially_relocatable<std::variant<int> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::variant<NotTriviallyCopyable> >::value, "");
+static_assert(std::__libcpp_is_trivially_relocatable<std::variant<std::unique_ptr<int> > >::value, "");
+
+static_assert(std::__libcpp_is_trivially_relocatable<std::variant<int, int> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::variant<NotTriviallyCopyable, int> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::variant<int, NotTriviallyCopyable> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::variant<NotTriviallyCopyable, NotTriviallyCopyable> >::value,
+              "");
+static_assert(std::__libcpp_is_trivially_relocatable<std::variant<std::unique_ptr<int>, std::unique_ptr<int> > >::value,
+              "");
+#endif // TEST_STD_VER >= 17
+
+// vector
+static_assert(std::__libcpp_is_trivially_relocatable<std::vector<int> >::value, "");
+static_assert(std::__libcpp_is_trivially_relocatable<std::vector<NotTriviallyCopyable> >::value, "");
+static_assert(!std::__libcpp_is_trivially_relocatable<std::vector<int, test_allocator<int> > >::value, "");
+
+// weak_ptr
+static_assert(std::__libcpp_is_trivially_relocatable<std::weak_ptr<NotTriviallyCopyable> >::value, "");
+
 // TODO: Mark all the trivially relocatable STL types as such


        


More information about the libcxx-commits mailing list