Quuxplusone updated this revision to Diff 155473.
Quuxplusone added a comment.

Move the functions from `<memory>` to `<vector>`, since that's their only 
caller.
Uniform treatment of the pointer/iterator parameters; discover that the 
difference between "copy_forward" and "copy_range_forward" was that the former 
did moves and the latter did copies. Rename accordingly.


Repository:
  rCXX libc++

https://reviews.llvm.org/D49317

Files:
  include/memory
  include/vector
  test/libcxx/containers/sequences/vector/specialized_allocator_traits.pass.cpp

Index: test/libcxx/containers/sequences/vector/specialized_allocator_traits.pass.cpp
===================================================================
--- /dev/null
+++ test/libcxx/containers/sequences/vector/specialized_allocator_traits.pass.cpp
@@ -0,0 +1,100 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <vector>
+
+// Test that vector does not use non-standard members of std::allocator_traits.
+// Specializing std::allocator_traits is arguably non-conforming, but libc++'s
+// support for specialized std::allocator_traits is a feature, not a bug.
+// Breaking (and subsequently deleting) this unit test should be done as a
+// conscious decision.
+
+#include <vector>
+
+template <class T>
+class A1
+{
+public:
+    using value_type = T;
+
+    A1() = default;
+
+    template <class U>
+    A1(const A1<U>&) {}
+
+    T *allocate(std::size_t n)
+    {
+        return (T *)std::malloc(n * sizeof (T));
+    }
+
+    void deallocate(T* p, std::size_t)
+    {
+        std::free(p);
+    }
+};
+
+template<class T>
+struct std::allocator_traits<A1<T>> {
+    using allocator_type = A1<T>;
+    using value_type = T;
+    using pointer = T*;
+    using const_pointer = const T*;
+    using void_pointer = void*;
+    using const_void_pointer = const void*;
+    using difference_type = std::ptrdiff_t;
+    using size_type = std::size_t;
+    using propagate_on_container_copy_assignment = std::true_type;
+    using propagate_on_container_move_assignment = std::true_type;
+    using propagate_on_container_swap = std::true_type;
+    using is_always_equal = std::true_type;
+
+    template<class U> using rebind_alloc = A1<U>;
+    template<class U> using rebind_traits = std::allocator_traits<A1<U>>;
+
+    static T *allocate(A1<T>& a, size_t n) {
+        return a.allocate(n);
+    }
+
+    static void deallocate(A1<T>& a, T *p, size_t n) {
+        return a.deallocate(p, n);
+    }
+
+    template<class U, class... Args>
+    static void construct(A1<T>&, U *p, Args&&... args) {
+        ::new ((void*)p) U(std::forward<Args>(args)...);
+    }
+
+    template<class U>
+    static void destroy(A1<T>&, U *p) {
+        p->~U();
+    }
+
+    static A1<T> select_on_container_copy_construction(const A1<T>& a) {
+        return a.select_on_container_copy_construction();
+    }
+
+    static size_type max_size(const A1<T>&) {
+        return size_t(-1);
+    }
+};
+
+int main()
+{
+    std::vector<int, A1<int>> v = {1, 2, 3};
+    v.resize(10);
+    v.insert(v.begin() + 4, 4);
+    assert(v[0] == 1);
+    assert(v[1] == 2);
+    assert(v[2] == 3);
+    assert(v[3] == 0);
+    assert(v[4] == 4);
+    assert(v[5] == 0);
+}
Index: include/vector
===================================================================
--- include/vector
+++ include/vector
@@ -291,6 +291,84 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+template <class _Alloc, class _Iter, class _Ptr, class _CopyViaMemcpy>
+_LIBCPP_INLINE_VISIBILITY
+inline void
+__copy_construct_forward(_Alloc& __a, _Iter __begin1, _Iter __end1,
+                         _Ptr& __begin2, _CopyViaMemcpy)
+{
+    using _Alloc_traits = allocator_traits<_Alloc>;
+    for (; __begin1 != __end1; ++__begin1, (void)++__begin2)
+        _Alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__begin2), *__begin1);
+}
+
+template <class _Alloc, class _Iter, class _Ptr>
+_LIBCPP_INLINE_VISIBILITY
+inline void
+__copy_construct_forward(_Alloc&, _Iter __begin1, _Iter __end1,
+                         _Ptr& __begin2, true_type)
+{
+    typedef typename iterator_traits<_Iter>::value_type _Tp;
+    typedef typename remove_const<_Tp>::type _Vp;
+    ptrdiff_t _Np = __end1 - __begin1;
+    if (_Np > 0) {
+        _VSTD::memcpy(const_cast<_Vp*>(_VSTD::__to_raw_pointer(__begin2)), _VSTD::__to_raw_pointer(__begin1), _Np * sizeof(_Tp));
+        __begin2 += _Np;
+    }
+}
+
+template <class _Alloc, class _Ptr>
+_LIBCPP_INLINE_VISIBILITY
+inline void
+__move_construct_forward(_Alloc& __a, _Ptr __begin1, _Ptr __end1,
+                         _Ptr& __begin2, false_type)
+{
+    using _Alloc_traits = allocator_traits<_Alloc>;
+    for (; __begin1 != __end1; ++__begin1, ++__begin2)
+        _Alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__begin2), _VSTD::move_if_noexcept(*__begin1));
+}
+
+template <class _Alloc, class _Ptr>
+_LIBCPP_INLINE_VISIBILITY
+inline void
+__move_construct_forward(_Alloc&, _Ptr __begin1, _Ptr __end1,
+                         _Ptr& __begin2, true_type)
+{
+    typedef typename iterator_traits<_Ptr>::value_type _Tp;
+    ptrdiff_t _Np = __end1 - __begin1;
+    if (_Np > 0) {
+        _VSTD::memcpy(_VSTD::__to_raw_pointer(__begin2), _VSTD::__to_raw_pointer(__begin1), _Np * sizeof(_Tp));
+        __begin2 += _Np;
+    }
+}
+
+template <class _Alloc, class _Ptr>
+_LIBCPP_INLINE_VISIBILITY
+inline void
+__move_construct_backward(_Alloc& __a, _Ptr __begin1, _Ptr __end1,
+                          _Ptr& __end2, false_type)
+{
+    using _Alloc_traits = allocator_traits<_Alloc>;
+    while (__end1 != __begin1) {
+        _Alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1));
+        --__end2;
+    }
+}
+
+template <class _Alloc, class _Ptr>
+_LIBCPP_INLINE_VISIBILITY
+inline void
+__move_construct_backward(_Alloc&, _Ptr __begin1, _Ptr __end1,
+                          _Ptr& __end2, true_type)
+{
+    typedef typename iterator_traits<_Ptr>::value_type _Tp;
+    ptrdiff_t _Np = __end1 - __begin1;
+    if (_Np > 0) {
+        __end2 -= _Np;
+        _VSTD::memcpy(_VSTD::__to_raw_pointer(__end2), _VSTD::__to_raw_pointer(__begin1), _Np * sizeof(_Tp));
+    }
+}
+
 template <bool>
 class __vector_base_common
 {
@@ -460,13 +538,20 @@
     }
 }
 
+template<class _Tp, class _Allocator>
+struct __vector_copy_via_memcpy : integral_constant<bool,
+    (is_same<_Allocator, allocator<_Tp> >::value || !__has_construct<_Allocator, _Tp*, _Tp>::value) &&
+    is_trivially_move_constructible<_Tp>::value
+> {};
+
 template <class _Tp, class _Allocator /* = allocator<_Tp> */>
 class _LIBCPP_TEMPLATE_VIS vector
     : private __vector_base<_Tp, _Allocator>
 {
 private:
     typedef __vector_base<_Tp, _Allocator>           __base;
     typedef allocator<_Tp>                           __default_allocator_type;
+
 public:
     typedef vector                                   __self;
     typedef _Tp                                      value_type;
@@ -927,8 +1012,9 @@
 void
 vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v)
 {
+    typedef typename __vector_copy_via_memcpy<_Tp, _Allocator>::type __copy_via_memcpy;
     __annotate_delete();
-    __alloc_traits::__construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_);
+    _VSTD::__move_construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_, __copy_via_memcpy());
     _VSTD::swap(this->__begin_, __v.__begin_);
     _VSTD::swap(this->__end_, __v.__end_);
     _VSTD::swap(this->__end_cap(), __v.__end_cap());
@@ -941,10 +1027,11 @@
 typename vector<_Tp, _Allocator>::pointer
 vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p)
 {
+    typedef typename __vector_copy_via_memcpy<_Tp, _Allocator>::type __copy_via_memcpy;
     __annotate_delete();
     pointer __r = __v.__begin_;
-    __alloc_traits::__construct_backward(this->__alloc(), this->__begin_, __p, __v.__begin_);
-    __alloc_traits::__construct_forward(this->__alloc(), __p, this->__end_, __v.__end_);
+    _VSTD::__move_construct_backward(this->__alloc(), this->__begin_, __p, __v.__begin_, __copy_via_memcpy());
+    _VSTD::__move_construct_forward(this->__alloc(), __p, this->__end_, __v.__end_, __copy_via_memcpy());
     _VSTD::swap(this->__begin_, __v.__begin_);
     _VSTD::swap(this->__end_, __v.__end_);
     _VSTD::swap(this->__end_cap(), __v.__end_cap());
@@ -1058,9 +1145,15 @@
 >::type
 vector<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last, size_type __n)
 {
+    typedef integral_constant<bool,
+        __vector_copy_via_memcpy<_Tp, _Allocator>::value &&
+        (is_same<_ForwardIterator, _Tp*>::value ||
+         is_same<_ForwardIterator, const _Tp*>::value ||
+         is_same<_ForwardIterator, pointer>::value)
+    > __copy_via_memcpy;
     allocator_type& __a = this->__alloc();
     __RAII_IncreaseAnnotator __annotator(*this, __n);
-    __alloc_traits::__construct_range_forward(__a, __first, __last, this->__end_);
+    _VSTD::__copy_construct_forward(__a, __first, __last, this->__end_, __copy_via_memcpy());
     __annotator.__done();
 }
 
Index: include/memory
===================================================================
--- include/memory
+++ include/memory
@@ -1606,98 +1606,6 @@
                 __has_select_on_container_copy_construction<const allocator_type>(),
                 __a);}
 
-    template <class _Ptr>
-        _LIBCPP_INLINE_VISIBILITY
-        static
-        void
-        __construct_forward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2)
-        {
-            for (; __begin1 != __end1; ++__begin1, ++__begin2)
-                construct(__a, _VSTD::__to_raw_pointer(__begin2), _VSTD::move_if_noexcept(*__begin1));
-        }
-
-    template <class _Tp>
-        _LIBCPP_INLINE_VISIBILITY
-        static
-        typename enable_if
-        <
-            (is_same<allocator_type, allocator<_Tp> >::value
-                || !__has_construct<allocator_type, _Tp*, _Tp>::value) &&
-             is_trivially_move_constructible<_Tp>::value,
-            void
-        >::type
-        __construct_forward(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __begin2)
-        {
-            ptrdiff_t _Np = __end1 - __begin1;
-            if (_Np > 0)
-            {
-                _VSTD::memcpy(__begin2, __begin1, _Np * sizeof(_Tp));
-                __begin2 += _Np;
-            }
-        }
-
-    template <class _Iter, class _Ptr>
-        _LIBCPP_INLINE_VISIBILITY
-        static
-        void
-        __construct_range_forward(allocator_type& __a, _Iter __begin1, _Iter __end1, _Ptr& __begin2)
-        {
-            for (; __begin1 != __end1; ++__begin1, (void) ++__begin2)
-                construct(__a, _VSTD::__to_raw_pointer(__begin2), *__begin1);
-        }
-
-    template <class _Tp>
-        _LIBCPP_INLINE_VISIBILITY
-        static
-        typename enable_if
-        <
-            (is_same<allocator_type, allocator<_Tp> >::value
-                || !__has_construct<allocator_type, _Tp*, _Tp>::value) &&
-             is_trivially_move_constructible<_Tp>::value,
-            void
-        >::type
-        __construct_range_forward(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __begin2)
-        {
-            typedef typename remove_const<_Tp>::type _Vp;
-            ptrdiff_t _Np = __end1 - __begin1;
-            if (_Np > 0)
-            {
-                _VSTD::memcpy(const_cast<_Vp*>(__begin2), __begin1, _Np * sizeof(_Tp));
-                __begin2 += _Np;
-            }
-        }
-
-    template <class _Ptr>
-        _LIBCPP_INLINE_VISIBILITY
-        static
-        void
-        __construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2)
-        {
-            while (__end1 != __begin1)
-            {
-                construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1));
-                --__end2;
-            }
-        }
-
-    template <class _Tp>
-        _LIBCPP_INLINE_VISIBILITY
-        static
-        typename enable_if
-        <
-            (is_same<allocator_type, allocator<_Tp> >::value
-                || !__has_construct<allocator_type, _Tp*, _Tp>::value) &&
-             is_trivially_move_constructible<_Tp>::value,
-            void
-        >::type
-        __construct_backward(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __end2)
-        {
-            ptrdiff_t _Np = __end1 - __begin1;
-            __end2 -= _Np;
-            if (_Np > 0)
-                _VSTD::memcpy(__end2, __begin1, _Np * sizeof(_Tp));
-        }
-
 private:
 
     _LIBCPP_INLINE_VISIBILITY
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to