[libcxx-commits] [libcxx] 2352fdd - Revert "[libc++] Optimize vector growing of trivially relocatable types (#76657)"

Kirill Stoimenov via libcxx-commits libcxx-commits at lists.llvm.org
Fri Feb 2 12:45:37 PST 2024


Author: Kirill Stoimenov
Date: 2024-02-02T20:43:51Z
New Revision: 2352fdd2026e36c4206053331deba1a70b70d925

URL: https://github.com/llvm/llvm-project/commit/2352fdd2026e36c4206053331deba1a70b70d925
DIFF: https://github.com/llvm/llvm-project/commit/2352fdd2026e36c4206053331deba1a70b70d925.diff

LOG: Revert "[libc++] Optimize vector growing of trivially relocatable types (#76657)"

Broke sanitizer bots: https://lab.llvm.org/buildbot/#/builders/5/builds/40641

This reverts commit 67eee4a029797c09129889c3655416d1be487cfe.

Added: 
    

Modified: 
    libcxx/benchmarks/ContainerBenchmarks.h
    libcxx/benchmarks/vector_operations.bench.cpp
    libcxx/docs/ReleaseNotes/19.rst
    libcxx/include/CMakeLists.txt
    libcxx/include/__memory/uninitialized_algorithms.h
    libcxx/include/__memory/unique_ptr.h
    libcxx/include/libcxx.imp
    libcxx/include/module.modulemap.in
    libcxx/include/string
    libcxx/include/vector
    libcxx/test/support/count_new.h

Removed: 
    libcxx/include/__type_traits/is_trivially_relocatable.h
    libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp


################################################################################
diff  --git a/libcxx/benchmarks/ContainerBenchmarks.h b/libcxx/benchmarks/ContainerBenchmarks.h
index 744505b439985..9a9abfd3b0d0f 100644
--- a/libcxx/benchmarks/ContainerBenchmarks.h
+++ b/libcxx/benchmarks/ContainerBenchmarks.h
@@ -80,7 +80,7 @@ void BM_ConstructFromRange(benchmark::State& st, Container, GenInputs gen) {
 }
 
 template <class Container>
-void BM_Pushback_no_grow(benchmark::State& state, Container c) {
+void BM_Pushback(benchmark::State& state, Container c) {
   int count = state.range(0);
   c.reserve(count);
   while (state.KeepRunningBatch(count)) {

diff  --git a/libcxx/benchmarks/vector_operations.bench.cpp b/libcxx/benchmarks/vector_operations.bench.cpp
index da21d1806c012..38b14c56756fb 100644
--- a/libcxx/benchmarks/vector_operations.bench.cpp
+++ b/libcxx/benchmarks/vector_operations.bench.cpp
@@ -1,7 +1,6 @@
 #include <cstdint>
 #include <cstdlib>
 #include <cstring>
-#include <deque>
 #include <functional>
 #include <vector>
 
@@ -40,21 +39,6 @@ BENCHMARK_CAPTURE(BM_ConstructFromRange, vector_size_t, std::vector<size_t>{}, g
 BENCHMARK_CAPTURE(BM_ConstructFromRange, vector_string, std::vector<std::string>{}, getRandomStringInputs)
     ->Arg(TestNumInputs);
 
-BENCHMARK_CAPTURE(BM_Pushback_no_grow, vector_int, std::vector<int>{})->Arg(TestNumInputs);
-
-template <class T>
-void bm_grow(benchmark::State& state) {
-  for (auto _ : state) {
-    std::vector<T> vec;
-    benchmark::DoNotOptimize(vec);
-    for (size_t i = 0; i != 2048; ++i)
-      vec.emplace_back();
-    benchmark::DoNotOptimize(vec);
-  }
-}
-BENCHMARK(bm_grow<int>);
-BENCHMARK(bm_grow<std::string>);
-BENCHMARK(bm_grow<std::unique_ptr<int>>);
-BENCHMARK(bm_grow<std::deque<int>>);
+BENCHMARK_CAPTURE(BM_Pushback, vector_int, std::vector<int>{})->Arg(TestNumInputs);
 
 BENCHMARK_MAIN();

diff  --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index 908d46b711a5a..db731de2e4399 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -44,8 +44,8 @@ Implemented Papers
 
 Improvements and New Features
 -----------------------------
+TODO
 
-- The performance of growing ``std::vector`` has been improved for trivially relocatable types.
 
 Deprecations and Removals
 -------------------------

diff  --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index d8ee598dc2633..6a845c813dc33 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -808,7 +808,6 @@ set(files
   __type_traits/is_trivially_lexicographically_comparable.h
   __type_traits/is_trivially_move_assignable.h
   __type_traits/is_trivially_move_constructible.h
-  __type_traits/is_trivially_relocatable.h
   __type_traits/is_unbounded_array.h
   __type_traits/is_union.h
   __type_traits/is_unsigned.h

diff  --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h
index 763701af9314f..9aff93a896486 100644
--- a/libcxx/include/__memory/uninitialized_algorithms.h
+++ b/libcxx/include/__memory/uninitialized_algorithms.h
@@ -29,7 +29,6 @@
 #include <__type_traits/is_trivially_copy_constructible.h>
 #include <__type_traits/is_trivially_move_assignable.h>
 #include <__type_traits/is_trivially_move_constructible.h>
-#include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/is_unbounded_array.h>
 #include <__type_traits/negation.h>
 #include <__type_traits/remove_const.h>
@@ -595,56 +594,60 @@ __uninitialized_allocator_copy(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1,
   return std::__rewrap_iter(__first2, __result);
 }
 
-template <class _Alloc, class _Type>
-struct __allocator_has_trivial_move_construct : _Not<__has_construct<_Alloc, _Type*, _Type&&> > {};
-
-template <class _Type>
-struct __allocator_has_trivial_move_construct<allocator<_Type>, _Type> : true_type {};
-
-template <class _Alloc, class _Tp>
-struct __allocator_has_trivial_destroy : _Not<__has_destroy<_Alloc, _Tp*> > {};
-
-template <class _Tp, class _Up>
-struct __allocator_has_trivial_destroy<allocator<_Tp>, _Up> : true_type {};
-
-// __uninitialized_allocator_relocate relocates the objects in [__first, __last) into __result.
-// Relocation means that the objects in [__first, __last) are placed into __result as-if by move-construct and destroy,
-// except that the move constructor and destructor may never be called if they are known to be equivalent to a memcpy.
-//
-// Preconditions:  __result doesn't contain any objects and [__first, __last) contains objects
-// Postconditions: __result contains the objects from [__first, __last) and
-//                 [__first, __last) doesn't contain any objects
+// Move-construct the elements [__first1, __last1) into [__first2, __first2 + N)
+// if the move constructor is noexcept, where N is distance(__first1, __last1).
 //
-// The strong exception guarantee is provided if any of the following are true:
-// - is_nothrow_move_constructible<_Tp>
-// - is_copy_constructible<_Tp>
-// - __libcpp_is_trivially_relocatable<_Tp>
-template <class _Alloc, class _Tp>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
-__uninitialized_allocator_relocate(_Alloc& __alloc, _Tp* __first, _Tp* __last, _Tp* __result) {
+// Otherwise try to copy all elements. If an exception is thrown the already copied
+// elements are destroyed in reverse order of their construction.
+template <class _Alloc, class _Iter1, class _Sent1, class _Iter2>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2
+__uninitialized_allocator_move_if_noexcept(_Alloc& __alloc, _Iter1 __first1, _Sent1 __last1, _Iter2 __first2) {
   static_assert(__is_cpp17_move_insertable<_Alloc>::value,
                 "The specified type does not meet the requirements of Cpp17MoveInsertable");
-  if (__libcpp_is_constant_evaluated() || !__libcpp_is_trivially_relocatable<_Tp>::value ||
-      !__allocator_has_trivial_move_construct<_Alloc, _Tp>::value ||
-      !__allocator_has_trivial_destroy<_Alloc, _Tp>::value) {
-    auto __destruct_first = __result;
-    auto __guard =
-        std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Tp*>(__alloc, __destruct_first, __result));
-    while (__first != __last) {
+  auto __destruct_first = __first2;
+  auto __guard =
+      std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Iter2>(__alloc, __destruct_first, __first2));
+  while (__first1 != __last1) {
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
-      allocator_traits<_Alloc>::construct(__alloc, __result, std::move_if_noexcept(*__first));
+    allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move_if_noexcept(*__first1));
 #else
-      allocator_traits<_Alloc>::construct(__alloc, __result, std::move(*__first));
+    allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__first2), std::move(*__first1));
 #endif
-      ++__first;
-      ++__result;
+    ++__first1;
+    ++__first2;
+  }
+  __guard.__complete();
+  return __first2;
+}
+
+template <class _Alloc, class _Type>
+struct __allocator_has_trivial_move_construct : _Not<__has_construct<_Alloc, _Type*, _Type&&> > {};
+
+template <class _Type>
+struct __allocator_has_trivial_move_construct<allocator<_Type>, _Type> : true_type {};
+
+#ifndef _LIBCPP_COMPILER_GCC
+template <
+    class _Alloc,
+    class _Iter1,
+    class _Iter2,
+    class _Type = typename iterator_traits<_Iter1>::value_type,
+    class = __enable_if_t<is_trivially_move_constructible<_Type>::value && is_trivially_move_assignable<_Type>::value &&
+                          __allocator_has_trivial_move_construct<_Alloc, _Type>::value> >
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Iter2
+__uninitialized_allocator_move_if_noexcept(_Alloc&, _Iter1 __first1, _Iter1 __last1, _Iter2 __first2) {
+  if (__libcpp_is_constant_evaluated()) {
+    while (__first1 != __last1) {
+      std::__construct_at(std::__to_address(__first2), std::move(*__first1));
+      ++__first1;
+      ++__first2;
     }
-    __guard.__complete();
-    std::__allocator_destroy(__alloc, __first, __last);
+    return __first2;
   } else {
-    __builtin_memcpy(__result, __first, sizeof(_Tp) * (__last - __first));
+    return std::move(__first1, __last1, __first2);
   }
 }
+#endif // _LIBCPP_COMPILER_GCC
 
 _LIBCPP_END_NAMESPACE_STD
 

diff  --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h
index a505dab8dd749..db473eaa50a6b 100644
--- a/libcxx/include/__memory/unique_ptr.h
+++ b/libcxx/include/__memory/unique_ptr.h
@@ -21,7 +21,6 @@
 #include <__memory/compressed_pair.h>
 #include <__type_traits/add_lvalue_reference.h>
 #include <__type_traits/common_type.h>
-#include <__type_traits/conditional.h>
 #include <__type_traits/dependent_type.h>
 #include <__type_traits/integral_constant.h>
 #include <__type_traits/is_array.h>
@@ -34,7 +33,6 @@
 #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/is_void.h>
 #include <__type_traits/remove_extent.h>
 #include <__type_traits/type_identity.h>
@@ -131,17 +129,6 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr {
 
   static_assert(!is_rvalue_reference<deleter_type>::value, "the specified deleter type cannot be an rvalue reference");
 
-  // A unique_ptr contains the following members which may be trivially relocatable:
-  // - pointer : this may be trivially relocatable, so it's checked
-  // - deleter_type: this may be trivially relocatable, so it's checked
-  //
-  // This unique_ptr implementation only contains a pointer to the unique object and a deleter, so there are no
-  // references to itself. This means that the entire structure is trivially relocatable if its members are.
-  using __trivially_relocatable = __conditional_t<
-      __libcpp_is_trivially_relocatable<pointer>::value && __libcpp_is_trivially_relocatable<deleter_type>::value,
-      unique_ptr,
-      void>;
-
 private:
   __compressed_pair<pointer, deleter_type> __ptr_;
 
@@ -289,17 +276,6 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp>
   typedef _Dp deleter_type;
   typedef typename __pointer<_Tp, deleter_type>::type pointer;
 
-  // A unique_ptr contains the following members which may be trivially relocatable:
-  // - pointer : this may be trivially relocatable, so it's checked
-  // - deleter_type: this may be trivially relocatable, so it's checked
-  //
-  // This unique_ptr implementation only contains a pointer to the unique object and a deleter, so there are no
-  // references to itself. This means that the entire structure is trivially relocatable if its members are.
-  using __trivially_relocatable = __conditional_t<
-      __libcpp_is_trivially_relocatable<pointer>::value && __libcpp_is_trivially_relocatable<deleter_type>::value,
-      unique_ptr,
-      void>;
-
 private:
   __compressed_pair<pointer, deleter_type> __ptr_;
 

diff  --git a/libcxx/include/__type_traits/is_trivially_relocatable.h b/libcxx/include/__type_traits/is_trivially_relocatable.h
deleted file mode 100644
index c0871731cc001..0000000000000
--- a/libcxx/include/__type_traits/is_trivially_relocatable.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_RELOCATABLE_H
-#define _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_RELOCATABLE_H
-
-#include <__config>
-#include <__type_traits/enable_if.h>
-#include <__type_traits/integral_constant.h>
-#include <__type_traits/is_same.h>
-#include <__type_traits/is_trivially_copyable.h>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#  pragma GCC system_header
-#endif
-
-_LIBCPP_BEGIN_NAMESPACE_STD
-
-// A type is trivially relocatable if a move construct + destroy of the original object is equivalent to
-// `memcpy(dst, src, sizeof(T))`.
-
-#if __has_builtin(__is_trivially_relocatable)
-template <class _Tp, class = void>
-struct __libcpp_is_trivially_relocatable : integral_constant<bool, __is_trivially_relocatable(_Tp)> {};
-#else
-template <class _Tp, class = void>
-struct __libcpp_is_trivially_relocatable : is_trivially_copyable<_Tp> {};
-#endif
-
-template <class _Tp>
-struct __libcpp_is_trivially_relocatable<_Tp,
-                                         __enable_if_t<is_same<_Tp, typename _Tp::__trivially_relocatable>::value> >
-    : true_type {};
-
-_LIBCPP_END_NAMESPACE_STD
-
-#endif // _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_RELOCATABLE_H

diff  --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp
index 8509c7e39a666..13c0dfeb2bc98 100644
--- a/libcxx/include/libcxx.imp
+++ b/libcxx/include/libcxx.imp
@@ -796,7 +796,6 @@
   { include: [ "<__type_traits/is_trivially_lexicographically_comparable.h>", "private", "<type_traits>", "public" ] },
   { include: [ "<__type_traits/is_trivially_move_assignable.h>", "private", "<type_traits>", "public" ] },
   { include: [ "<__type_traits/is_trivially_move_constructible.h>", "private", "<type_traits>", "public" ] },
-  { include: [ "<__type_traits/is_trivially_relocatable.h>", "private", "<type_traits>", "public" ] },
   { include: [ "<__type_traits/is_unbounded_array.h>", "private", "<type_traits>", "public" ] },
   { include: [ "<__type_traits/is_union.h>", "private", "<type_traits>", "public" ] },
   { include: [ "<__type_traits/is_unsigned.h>", "private", "<type_traits>", "public" ] },

diff  --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index ddb0f4b70e02b..03f71290b6603 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1970,7 +1970,6 @@ module std_private_type_traits_is_trivially_destructible                 [system
 module std_private_type_traits_is_trivially_lexicographically_comparable [system] { header "__type_traits/is_trivially_lexicographically_comparable.h" }
 module std_private_type_traits_is_trivially_move_assignable              [system] { header "__type_traits/is_trivially_move_assignable.h" }
 module std_private_type_traits_is_trivially_move_constructible           [system] { header "__type_traits/is_trivially_move_constructible.h" }
-module std_private_type_traits_is_trivially_relocatable                  [system] { header "__type_traits/is_trivially_relocatable.h" }
 module std_private_type_traits_is_unbounded_array                        [system] { header "__type_traits/is_unbounded_array.h" }
 module std_private_type_traits_is_union                                  [system] { header "__type_traits/is_union.h" }
 module std_private_type_traits_is_unsigned                               [system] { header "__type_traits/is_unsigned.h" }

diff  --git a/libcxx/include/string b/libcxx/include/string
index ed4fdbe6864c2..efdff3dd42da0 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -599,7 +599,6 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len );
 #include <__ranges/size.h>
 #include <__string/char_traits.h>
 #include <__string/extern_template_lists.h>
-#include <__type_traits/conditional.h>
 #include <__type_traits/is_allocator.h>
 #include <__type_traits/is_array.h>
 #include <__type_traits/is_convertible.h>
@@ -608,7 +607,6 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len );
 #include <__type_traits/is_same.h>
 #include <__type_traits/is_standard_layout.h>
 #include <__type_traits/is_trivial.h>
-#include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/noexcept_move_assign_container.h>
 #include <__type_traits/remove_cvref.h>
 #include <__type_traits/void_t.h>
@@ -726,20 +724,6 @@ public:
   typedef typename __alloc_traits::pointer pointer;
   typedef typename __alloc_traits::const_pointer const_pointer;
 
-  // A basic_string contains the following members which may be trivially relocatable:
-  // - pointer: is currently assumed to be trivially relocatable, but is still checked in case that changes
-  // - size_type: is always trivially relocatable, since it has to be an integral type
-  // - value_type: is always trivially relocatable, since it has to be trivial
-  // - unsigned char: is a fundamental type, so it's trivially relocatable
-  // - allocator_type: may or may not be trivially relocatable, so it's checked
-  //
-  // This string implementation doesn't contain any references into itself. It only contains a bit that says whether
-  // it is in small or large string mode, so the entire structure is trivially relocatable if its members are.
-  using __trivially_relocatable = __conditional_t<
-      __libcpp_is_trivially_relocatable<allocator_type>::value && __libcpp_is_trivially_relocatable<pointer>::value,
-      basic_string,
-      void>;
-
   static_assert((!is_array<value_type>::value), "Character type of basic_string must not be an array");
   static_assert((is_standard_layout<value_type>::value), "Character type of basic_string must be standard-layout");
   static_assert((is_trivial<value_type>::value), "Character type of basic_string must be trivial");

diff  --git a/libcxx/include/vector b/libcxx/include/vector
index e9615ab4c9a30..5e2027ea21a39 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -982,18 +982,14 @@ template <ranges::input_range _Range,
 vector(from_range_t, _Range&&, _Alloc = _Alloc()) -> vector<ranges::range_value_t<_Range>, _Alloc>;
 #endif
 
-// __swap_out_circular_buffer relocates the objects in [__begin_, __end_) into the front of __v and swaps the buffers of
-// *this and __v. It is assumed that __v provides space for exactly (__end_ - __begin_) objects in the front. This
-// function has a strong exception guarantee.
 template <class _Tp, class _Allocator>
 _LIBCPP_CONSTEXPR_SINCE_CXX20 void
 vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v) {
   __annotate_delete();
-  auto __new_begin = __v.__begin_ - (__end_ - __begin_);
-  std::__uninitialized_allocator_relocate(
-      __alloc(), std::__to_address(__begin_), std::__to_address(__end_), std::__to_address(__new_begin));
-  __v.__begin_ = __new_begin;
-  __end_       = __begin_; // All the objects have been destroyed by relocating them.
+  using _RevIter = std::reverse_iterator<pointer>;
+  __v.__begin_   = std::__uninitialized_allocator_move_if_noexcept(
+                     __alloc(), _RevIter(__end_), _RevIter(__begin_), _RevIter(__v.__begin_))
+                     .base();
   std::swap(this->__begin_, __v.__begin_);
   std::swap(this->__end_, __v.__end_);
   std::swap(this->__end_cap(), __v.__end_cap());
@@ -1001,35 +997,22 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
   __annotate_new(size());
 }
 
-// __swap_out_circular_buffer relocates the objects in [__begin_, __p) into the front of __v, the objects in
-// [__p, __end_) into the back of __v and swaps the buffers of *this and __v. It is assumed that __v provides space for
-// exactly (__p - __begin_) objects in the front and space for at least (__end_ - __p) objects in the back. This
-// function has a strong exception guarantee if __begin_ == __p || __end_ == __p.
 template <class _Tp, class _Allocator>
 _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
 vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p) {
   __annotate_delete();
-  pointer __ret = __v.__begin_;
-
-  // Relocate [__p, __end_) first to avoid having a hole in [__begin_, __end_)
-  // in case something in [__begin_, __p) throws.
-  std::__uninitialized_allocator_relocate(
-      __alloc(), std::__to_address(__p), std::__to_address(__end_), std::__to_address(__v.__end_));
-  __v.__end_ += (__end_ - __p);
-  __end_           = __p; // The objects in [__p, __end_) have been destroyed by relocating them.
-  auto __new_begin = __v.__begin_ - (__p - __begin_);
-
-  std::__uninitialized_allocator_relocate(
-      __alloc(), std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin));
-  __v.__begin_ = __new_begin;
-  __end_       = __begin_; // All the objects have been destroyed by relocating them.
-
+  pointer __r    = __v.__begin_;
+  using _RevIter = std::reverse_iterator<pointer>;
+  __v.__begin_   = std::__uninitialized_allocator_move_if_noexcept(
+                     __alloc(), _RevIter(__p), _RevIter(__begin_), _RevIter(__v.__begin_))
+                     .base();
+  __v.__end_ = std::__uninitialized_allocator_move_if_noexcept(__alloc(), __p, __end_, __v.__end_);
   std::swap(this->__begin_, __v.__begin_);
   std::swap(this->__end_, __v.__end_);
   std::swap(this->__end_cap(), __v.__end_cap());
   __v.__first_ = __v.__begin_;
   __annotate_new(size());
-  return __ret;
+  return __r;
 }
 
 template <class _Tp, class _Allocator>

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
deleted file mode 100644
index 389816bb23aa9..0000000000000
--- a/libcxx/test/libcxx/type_traits/is_trivially_relocatable.compile.pass.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#include <__type_traits/is_trivially_relocatable.h>
-#include <memory>
-#include <string>
-
-#include "constexpr_char_traits.h"
-#include "test_allocator.h"
-
-static_assert(std::__libcpp_is_trivially_relocatable<char>::value, "");
-static_assert(std::__libcpp_is_trivially_relocatable<int>::value, "");
-static_assert(std::__libcpp_is_trivially_relocatable<double>::value, "");
-
-struct Empty {};
-static_assert(std::__libcpp_is_trivially_relocatable<Empty>::value, "");
-
-struct TriviallyCopyable {
-  char c;
-  int i;
-  Empty s;
-};
-static_assert(std::__libcpp_is_trivially_relocatable<TriviallyCopyable>::value, "");
-
-struct NotTriviallyCopyable {
-  NotTriviallyCopyable(const NotTriviallyCopyable&);
-  ~NotTriviallyCopyable();
-};
-static_assert(!std::__libcpp_is_trivially_relocatable<NotTriviallyCopyable>::value, "");
-
-struct MoveOnlyTriviallyCopyable {
-  MoveOnlyTriviallyCopyable(const MoveOnlyTriviallyCopyable&)            = delete;
-  MoveOnlyTriviallyCopyable& operator=(const MoveOnlyTriviallyCopyable&) = delete;
-  MoveOnlyTriviallyCopyable(MoveOnlyTriviallyCopyable&&)                 = default;
-  MoveOnlyTriviallyCopyable& operator=(MoveOnlyTriviallyCopyable&&)      = default;
-};
-#ifndef _MSC_VER
-static_assert(std::__libcpp_is_trivially_relocatable<MoveOnlyTriviallyCopyable>::value, "");
-#else
-static_assert(!std::__libcpp_is_trivially_relocatable<MoveOnlyTriviallyCopyable>::value, "");
-#endif
-// standard library types
-// ----------------------
-
-// basic_string
-struct MyChar {
-  char c;
-};
-template <class T>
-struct NotTriviallyRelocatableCharTraits : constexpr_char_traits<T> {
-  NotTriviallyRelocatableCharTraits(const NotTriviallyRelocatableCharTraits&);
-  NotTriviallyRelocatableCharTraits& operator=(const NotTriviallyRelocatableCharTraits&);
-  ~NotTriviallyRelocatableCharTraits();
-};
-
-static_assert(std::__libcpp_is_trivially_relocatable<
-                  std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::value,
-              "");
-static_assert(std::__libcpp_is_trivially_relocatable<
-                  std::basic_string<char, NotTriviallyRelocatableCharTraits<char>, std::allocator<char> > >::value,
-              "");
-static_assert(std::__libcpp_is_trivially_relocatable<
-                  std::basic_string<MyChar, constexpr_char_traits<MyChar>, std::allocator<MyChar> > >::value,
-              "");
-static_assert(
-    std::__libcpp_is_trivially_relocatable<
-        std::basic_string<MyChar, NotTriviallyRelocatableCharTraits<MyChar>, std::allocator<MyChar> > >::value,
-    "");
-static_assert(!std::__libcpp_is_trivially_relocatable<
-                  std::basic_string<char, std::char_traits<char>, test_allocator<char> > >::value,
-              "");
-static_assert(
-    !std::__libcpp_is_trivially_relocatable<
-        std::basic_string<MyChar, NotTriviallyRelocatableCharTraits<MyChar>, test_allocator<MyChar> > >::value,
-    "");
-
-// unique_ptr
-struct NotTriviallyRelocatableDeleter {
-  NotTriviallyRelocatableDeleter(const NotTriviallyRelocatableDeleter&);
-  NotTriviallyRelocatableDeleter& operator=(const NotTriviallyRelocatableDeleter&);
-  ~NotTriviallyRelocatableDeleter();
-
-  template <class T>
-  void operator()(T*);
-};
-
-struct NotTriviallyRelocatablePointer {
-  struct pointer {
-    pointer(const pointer&);
-    pointer& operator=(const pointer&);
-    ~pointer();
-  };
-
-  template <class T>
-  void operator()(T*);
-};
-
-static_assert(std::__libcpp_is_trivially_relocatable<std::unique_ptr<int> >::value, "");
-static_assert(std::__libcpp_is_trivially_relocatable<std::unique_ptr<NotTriviallyCopyable> >::value, "");
-static_assert(std::__libcpp_is_trivially_relocatable<std::unique_ptr<int[]> >::value, "");
-static_assert(!std::__libcpp_is_trivially_relocatable<std::unique_ptr<int, NotTriviallyRelocatableDeleter> >::value,
-              "");
-static_assert(!std::__libcpp_is_trivially_relocatable<std::unique_ptr<int[], NotTriviallyRelocatableDeleter> >::value,
-              "");
-static_assert(!std::__libcpp_is_trivially_relocatable<std::unique_ptr<int, NotTriviallyRelocatablePointer> >::value,
-              "");
-static_assert(!std::__libcpp_is_trivially_relocatable<std::unique_ptr<int[], NotTriviallyRelocatablePointer> >::value,
-              "");
-
-// TODO: Mark all the trivially relocatable STL types as such

diff  --git a/libcxx/test/support/count_new.h b/libcxx/test/support/count_new.h
index dd8c0e54cae7f..0d17e394d0312 100644
--- a/libcxx/test/support/count_new.h
+++ b/libcxx/test/support/count_new.h
@@ -99,18 +99,15 @@ class MemCounter
 
     void deleteCalled(void * p)
     {
-      if (p) {
+        assert(p);
         --outstanding_new;
         ++delete_called;
-      }
     }
 
     void alignedDeleteCalled(void *p, std::size_t a) {
-      if (p) {
-        deleteCalled(p);
-        ++aligned_delete_called;
-        last_delete_align = a;
-      }
+      deleteCalled(p);
+      ++aligned_delete_called;
+      last_delete_align = a;
     }
 
     void newArrayCalled(std::size_t s)


        


More information about the libcxx-commits mailing list