diff options
author | Tom Stellard <tstellar@redhat.com> | 2017-11-22 15:06:35 +0000 |
---|---|---|
committer | Tom Stellard <tstellar@redhat.com> | 2017-11-22 15:06:35 +0000 |
commit | 598ae4fa2e4da8b0a4b839c8c26b6cd3f672a968 (patch) | |
tree | a42814e786626dd74bd3d1fee4221a2eab71c60e /test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp | |
parent | 1496b0e710aa010a384910b36d10a257cdeae2b7 (diff) |
Merging r315994:release_50
------------------------------------------------------------------------
r315994 | ericwf | 2017-10-17 06:03:17 -0700 (Tue, 17 Oct 2017) | 18 lines
[libc++] Fix PR34898 - vector iterator constructors and assign method perform push_back instead of emplace_back.
Summary:
The constructors `vector(Iter, Iter, Alloc = Alloc{})` and `assign(Iter, Iter)` don't correctly perform EmplaceConstruction from the result of dereferencing the iterator. This results in them performing an additional and unneeded copy.
This patch addresses the issue by correctly using `emplace_back` in C++11 and newer.
There are also some bugs in our `insert` implementation, but those will be handled separately.
@mclow.lists We should probably merge this into 5.1, agreed?
Reviewers: mclow.lists, dlj, EricWF
Reviewed By: mclow.lists, EricWF
Subscribers: cfe-commits, mclow.lists
Differential Revision: https://reviews.llvm.org/D38757
------------------------------------------------------------------------
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/branches/release_50@318837 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp')
-rw-r--r-- | test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp | 160 |
1 files changed, 128 insertions, 32 deletions
diff --git a/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp b/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp index b4482ddb2..71743b31d 100644 --- a/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp +++ b/test/std/containers/sequences/vector/vector.cons/construct_iter_iter_alloc.pass.cpp @@ -21,56 +21,152 @@ #include "test_allocator.h" #include "min_allocator.h" #include "asan_testing.h" +#if TEST_STD_VER >= 11 +#include "emplace_constructible.h" +#include "container_test_types.h" +#endif template <class C, class Iterator, class A> -void -test(Iterator first, Iterator last, const A& a) -{ - C c(first, last, a); - LIBCPP_ASSERT(c.__invariants()); - assert(c.size() == static_cast<std::size_t>(std::distance(first, last))); - LIBCPP_ASSERT(is_contiguous_container_asan_correct(c)); - for (typename C::const_iterator i = c.cbegin(), e = c.cend(); i != e; ++i, ++first) - assert(*i == *first); +void test(Iterator first, Iterator last, const A& a) { + C c(first, last, a); + LIBCPP_ASSERT(c.__invariants()); + assert(c.size() == static_cast<std::size_t>(std::distance(first, last))); + LIBCPP_ASSERT(is_contiguous_container_asan_correct(c)); + for (typename C::const_iterator i = c.cbegin(), e = c.cend(); i != e; + ++i, ++first) + assert(*i == *first); } #if TEST_STD_VER >= 11 template <class T> -struct implicit_conv_allocator : min_allocator<T> -{ - implicit_conv_allocator(void*) {} - implicit_conv_allocator(const implicit_conv_allocator&) = default; +struct implicit_conv_allocator : min_allocator<T> { + implicit_conv_allocator(void*) {} + implicit_conv_allocator(const implicit_conv_allocator&) = default; - template <class U> - implicit_conv_allocator(implicit_conv_allocator<U>) {} + template <class U> + implicit_conv_allocator(implicit_conv_allocator<U>) {} }; #endif -int main() -{ - { +void basic_tests() { + { int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0}; - int* an = a + sizeof(a)/sizeof(a[0]); + int* an = a + sizeof(a) / sizeof(a[0]); std::allocator<int> alloc; - test<std::vector<int> >(input_iterator<const int*>(a), input_iterator<const int*>(an), alloc); - test<std::vector<int> >(forward_iterator<const int*>(a), forward_iterator<const int*>(an), alloc); - test<std::vector<int> >(bidirectional_iterator<const int*>(a), bidirectional_iterator<const int*>(an), alloc); - test<std::vector<int> >(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an), alloc); + test<std::vector<int> >(input_iterator<const int*>(a), + input_iterator<const int*>(an), alloc); + test<std::vector<int> >(forward_iterator<const int*>(a), + forward_iterator<const int*>(an), alloc); + test<std::vector<int> >(bidirectional_iterator<const int*>(a), + bidirectional_iterator<const int*>(an), alloc); + test<std::vector<int> >(random_access_iterator<const int*>(a), + random_access_iterator<const int*>(an), alloc); test<std::vector<int> >(a, an, alloc); - } + } #if TEST_STD_VER >= 11 - { + { int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0}; - int* an = a + sizeof(a)/sizeof(a[0]); + int* an = a + sizeof(a) / sizeof(a[0]); min_allocator<int> alloc; - test<std::vector<int, min_allocator<int>> >(input_iterator<const int*>(a), input_iterator<const int*>(an), alloc); - test<std::vector<int, min_allocator<int>> >(forward_iterator<const int*>(a), forward_iterator<const int*>(an), alloc); - test<std::vector<int, min_allocator<int>> >(bidirectional_iterator<const int*>(a), bidirectional_iterator<const int*>(an), alloc); - test<std::vector<int, min_allocator<int>> >(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an), alloc); - test<std::vector<int, min_allocator<int>> >(a, an, alloc); - test<std::vector<int, implicit_conv_allocator<int>> >(a, an, nullptr); + test<std::vector<int, min_allocator<int> > >( + input_iterator<const int*>(a), input_iterator<const int*>(an), alloc); + test<std::vector<int, min_allocator<int> > >( + forward_iterator<const int*>(a), forward_iterator<const int*>(an), + alloc); + test<std::vector<int, min_allocator<int> > >( + bidirectional_iterator<const int*>(a), + bidirectional_iterator<const int*>(an), alloc); + test<std::vector<int, min_allocator<int> > >( + random_access_iterator<const int*>(a), + random_access_iterator<const int*>(an), alloc); + test<std::vector<int, min_allocator<int> > >(a, an, alloc); + test<std::vector<int, implicit_conv_allocator<int> > >(a, an, nullptr); + } +#endif +} + +void emplaceable_concept_tests() { +#if TEST_STD_VER >= 11 + int arr1[] = {42}; + int arr2[] = {1, 101, 42}; + { + using T = EmplaceConstructible<int>; + using It = forward_iterator<int*>; + using Alloc = std::allocator<T>; + Alloc a; + { + std::vector<T> v(It(arr1), It(std::end(arr1)), a); + assert(v[0].value == 42); + } + { + std::vector<T> v(It(arr2), It(std::end(arr2)), a); + assert(v[0].value == 1); + assert(v[1].value == 101); + assert(v[2].value == 42); + } + } + { + using T = EmplaceConstructibleAndMoveInsertable<int>; + using It = input_iterator<int*>; + using Alloc = std::allocator<T>; + Alloc a; + { + std::vector<T> v(It(arr1), It(std::end(arr1)), a); + assert(v[0].copied == 0); + assert(v[0].value == 42); + } + { + std::vector<T> v(It(arr2), It(std::end(arr2)), a); + assert(v[0].value == 1); + assert(v[1].value == 101); + assert(v[2].copied == 0); + assert(v[2].value == 42); } + } #endif } + +void test_ctor_under_alloc() { +#if TEST_STD_VER >= 11 + int arr1[] = {42}; + int arr2[] = {1, 101, 42}; + { + using C = TCT::vector<>; + using T = typename C::value_type; + using It = forward_iterator<int*>; + using Alloc = typename C::allocator_type; + Alloc a; + { + ExpectConstructGuard<int&> G(1); + C v(It(arr1), It(std::end(arr1)), a); + } + { + ExpectConstructGuard<int&> G(3); + C v(It(arr2), It(std::end(arr2)), a); + } + } + { + using C = TCT::vector<>; + using T = typename C::value_type; + using It = input_iterator<int*>; + using Alloc = typename C::allocator_type; + Alloc a; + { + ExpectConstructGuard<int&> G(1); + C v(It(arr1), It(std::end(arr1)), a); + } + { + //ExpectConstructGuard<int&> G(3); + //C v(It(arr2), It(std::end(arr2)), a); + } + } +#endif +} + +int main() { + basic_tests(); + emplaceable_concept_tests(); // See PR34898 + test_ctor_under_alloc(); +} |