Index: libcxx/test/std/containers/sequences/vector/access.pass.cpp =================================================================== --- libcxx/test/std/containers/sequences/vector/access.pass.cpp +++ libcxx/test/std/containers/sequences/vector/access.pass.cpp @@ -29,7 +29,7 @@ template C -make(int size, int start = 0) +make(int size, int start) { C c; for (int i = 0; i < size; ++i) @@ -37,84 +37,85 @@ return c; } -int main(int, char**) -{ - { - typedef std::vector C; - C c = make(10); - LIBCPP_ASSERT_NOEXCEPT(c[0]); - LIBCPP_ASSERT_NOEXCEPT(c.front()); - LIBCPP_ASSERT_NOEXCEPT(c.back()); - // at() is NOT noexcept - ASSERT_SAME_TYPE(C::reference, decltype(c[0])); - ASSERT_SAME_TYPE(C::reference, decltype(c.at(0))); - ASSERT_SAME_TYPE(C::reference, decltype(c.front())); - ASSERT_SAME_TYPE(C::reference, decltype(c.back())); - for (int i = 0; i < 10; ++i) - assert(c[i] == i); - for (int i = 0; i < 10; ++i) - assert(c.at(i) == i); - assert(c.front() == 0); - assert(c.back() == 9); +template +void test_get_basic(Vector& c, int start_value) { + const int n = c.size(); + for (int i = 0; i < n; ++i) + assert(c[i] == start_value + i); + for (int i = 0; i < n; ++i) + assert(c.at(i) == start_value + i); + +#ifndef TEST_HAS_NO_EXCEPTIONS + try { + c.at(n); + assert(false); + } catch (const std::out_of_range&) {} +#endif + + assert(c.front() == start_value); + assert(c.back() == start_value + n - 1); +} + +template +void test_get() { + int start_value = 35; + Vector c = make(10, start_value); + const Vector& cc = c; + test_get_basic(c, start_value); + test_get_basic(cc, start_value); +} + +template +void test_set() { + int start_value = 35; + const int n = 10; + Vector c = make(n, start_value); + + for (int i = 0; i < n; ++i) { + assert(c[i] == start_value + i); + c[i] = start_value + i + 1; + assert(c[i] == start_value + i + 1); } - { - typedef std::vector C; - const int N = 5; - const C c = make(10, N); - LIBCPP_ASSERT_NOEXCEPT(c[0]); - LIBCPP_ASSERT_NOEXCEPT(c.front()); - LIBCPP_ASSERT_NOEXCEPT(c.back()); - // at() is NOT noexcept - ASSERT_SAME_TYPE(C::const_reference, decltype(c[0])); - ASSERT_SAME_TYPE(C::const_reference, decltype(c.at(0))); - ASSERT_SAME_TYPE(C::const_reference, decltype(c.front())); - ASSERT_SAME_TYPE(C::const_reference, decltype(c.back())); - for (int i = 0; i < 10; ++i) - assert(c[i] == N + i); - for (int i = 0; i < 10; ++i) - assert(c.at(i) == N + i); - assert(c.front() == N); - assert(c.back() == N + 9); + for (int i = 0; i < n; ++i) { + assert(c.at(i) == start_value + i + 1); + c.at(i) = start_value + i + 2; + assert(c.at(i) == start_value + i + 2); } + + assert(c.front() == start_value + 2); + c.front() = start_value + 3; + assert(c.front() == start_value + 3); + + assert(c.back() == start_value + n + 1); + c.back() = start_value + n + 2; + assert(c.back() == start_value + n + 2); +} + +template +void test() { + test_get(); + test_set(); + + Vector c; + const Vector& cc = c; + ASSERT_SAME_TYPE(typename Vector::reference, decltype(c[0])); + ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc[0])); + + ASSERT_SAME_TYPE(typename Vector::reference, decltype(c.at(0))); + ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.at(0))); + + ASSERT_SAME_TYPE(typename Vector::reference, decltype(c.front())); + ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.front())); + + ASSERT_SAME_TYPE(typename Vector::reference, decltype(c.back())); + ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.back())); +} + +int main(int, char**) +{ + test >(); #if TEST_STD_VER >= 11 - { - typedef std::vector> C; - const int N = 34; - C c = make(10, N); - LIBCPP_ASSERT_NOEXCEPT(c[0]); - LIBCPP_ASSERT_NOEXCEPT(c.front()); - LIBCPP_ASSERT_NOEXCEPT(c.back()); - // at() is NOT noexcept - ASSERT_SAME_TYPE(C::reference, decltype(c[0])); - ASSERT_SAME_TYPE(C::reference, decltype(c.at(0))); - ASSERT_SAME_TYPE(C::reference, decltype(c.front())); - ASSERT_SAME_TYPE(C::reference, decltype(c.back())); - for (int i = 0; i < 10; ++i) - assert(c[i] == N + i); - for (int i = 0; i < 10; ++i) - assert(c.at(i) == N + i); - assert(c.front() == N); - assert(c.back() == N + 9); - } - { - typedef std::vector> C; - const int N = 23; - const C c = make(10, N); - LIBCPP_ASSERT_NOEXCEPT(c[0]); - LIBCPP_ASSERT_NOEXCEPT(c.front()); - LIBCPP_ASSERT_NOEXCEPT(c.back()); - // at() is NOT noexcept - ASSERT_SAME_TYPE(C::const_reference, decltype(c[0])); - ASSERT_SAME_TYPE(C::const_reference, decltype(c.at(0))); - ASSERT_SAME_TYPE(C::const_reference, decltype(c.front())); - ASSERT_SAME_TYPE(C::const_reference, decltype(c.back())); - for (int i = 0; i < 10; ++i) - assert(c[i] == N + i); - for (int i = 0; i < 10; ++i) - assert(c.at(i) == N + i); - assert(c.front() == N); - assert(c.back() == N + 9); - } + test > >(); #endif return 0; Index: libcxx/test/std/containers/sequences/vector/reverse_iterators.pass.cpp =================================================================== --- /dev/null +++ libcxx/test/std/containers/sequences/vector/reverse_iterators.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// + +// reverse_iterator rbegin(); +// reverse_iterator rend(); +// const_reverse_iterator rbegin() const; +// const_reverse_iterator rend() const; +// const_reverse_iterator crbegin() const; +// const_reverse_iterator crend() const; + +#include +#include +#include + +#include "min_allocator.h" + +template +void check_vector_reverse_iterators() { + { + Vector vec; + assert(vec.rbegin() == vec.rend()); + assert(vec.crbegin() == vec.crend()); + } + { + Vector vec; + const Vector& cvec = vec; + vec.reserve(10); + for (int i = 0; i < 10; ++i) + vec.push_back(i); + { + int iterations = 0; + + for (typename Vector::const_reverse_iterator it = vec.crbegin(); it != vec.crend(); ++it) { + assert(*it == (10 - iterations - 1)); + ++iterations; + } + assert(iterations == 10); + } + { + assert(cvec.rbegin() == vec.crbegin()); + assert(cvec.rend() == vec.crend()); + } + { + int iterations = 0; + + for (typename Vector::reverse_iterator it = vec.rbegin(); it != vec.rend(); ++it) { + assert(*it == (10 - iterations - 1)); + *it = 40; + assert(*it == 40); + ++iterations; + } + assert(iterations == 10); + } + + assert(std::distance(vec.rbegin(), vec.rend()) == 10); + assert(std::distance(cvec.rbegin(), cvec.rend()) == 10); + assert(std::distance(vec.crbegin(), vec.crend()) == 10); + assert(std::distance(cvec.crbegin(), cvec.crend()) == 10); + } +} + +int main(int, char**) { + check_vector_reverse_iterators >(); +#if TEST_STD_VER >= 11 + check_vector_reverse_iterators > >(); +#endif + + return 0; +} Index: libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp =================================================================== --- libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp +++ libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp @@ -48,6 +48,39 @@ assert(v.capacity() == 150); assert(is_contiguous_container_asan_correct(v)); } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + std::vector v; + size_t sz = v.max_size() + 1; + + try { + v.reserve(sz); + assert(false); + } catch (const std::length_error&) { + assert(v.size() == 0); + assert(v.capacity() == 0); + } + } + { + std::vector v(10, 42); + int* previous_data = v.data(); + size_t previous_capacity = v.capacity(); + size_t sz = v.max_size() + 1; + + try { + v.reserve(sz); + assert(false); + } catch (std::length_error&) { + assert(v.size() == 10); + assert(v.capacity() == previous_capacity); + assert(v.data() == previous_data); + + for (int i = 0; i < 10; ++i) { + assert(v[i] == 42); + } + } + } +#endif #if TEST_STD_VER >= 11 { std::vector> v; Index: libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp =================================================================== --- libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp +++ libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp @@ -15,6 +15,7 @@ #include "test_macros.h" #include "test_allocator.h" #include "min_allocator.h" +#include "allocators.h" int main(int, char**) { @@ -33,6 +34,44 @@ assert(l2.get_allocator() == other_allocator(5)); } #if TEST_STD_VER >= 11 + { + // Test with Allocator::propagate_on_container_copy_assignment == false_type + using Alloc = NonPOCCAAllocator; + bool copy_assigned_into = false; + std::vector l(3, 2, Alloc(5, nullptr)); + std::vector l2(l, Alloc(3, ©_assigned_into)); + assert(!copy_assigned_into); + l2 = l; + assert(!copy_assigned_into); + assert(l2 == l); + assert(l2.get_allocator() == Alloc(3, nullptr)); + } + { + // Test with Allocator::propagate_on_container_copy_assignment == true_type + // and equal allocators + using Alloc = POCCAAllocator; + bool copy_assigned_into = false; + std::vector l(3, 2, Alloc(5, nullptr)); + std::vector l2(l, Alloc(5, ©_assigned_into)); + assert(!copy_assigned_into); + l2 = l; + assert(copy_assigned_into); + assert(l2 == l); + assert(l2.get_allocator() == Alloc(5, nullptr)); + } + { + // Test with Allocator::propagate_on_container_copy_assignment == true_type + // and unequal allocators + using Alloc = POCCAAllocator; + bool copy_assigned_into = false; + std::vector l(3, 2, Alloc(5, nullptr)); + std::vector l2(l, Alloc(3, ©_assigned_into)); + assert(!copy_assigned_into); + l2 = l; + assert(copy_assigned_into); + assert(l2 == l); + assert(l2.get_allocator() == Alloc(5, nullptr)); + } { std::vector > l(3, 2, min_allocator()); std::vector > l2(l, min_allocator()); Index: libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_extra.pass.cpp =================================================================== --- libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_extra.pass.cpp +++ libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_extra.pass.cpp @@ -57,6 +57,19 @@ assert(v[0] == 3); assert(is_contiguous_container_asan_correct(v)); } + { + std::vector v; + v.reserve(8); + size_t old_capacity = v.capacity(); + assert(old_capacity >= 8); + v.resize(4); // keep the existing capacity + assert(v.capacity() == old_capacity); + + v.emplace(v.cend(), 42); + assert(v.size() == 5); + assert(v.capacity() == old_capacity); + assert(v[4] == 42); + } return 0; } Index: libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_lvalue.pass.cpp =================================================================== --- libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_lvalue.pass.cpp +++ libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_lvalue.pass.cpp @@ -23,7 +23,8 @@ { { std::vector v(100); - std::vector::iterator i = v.insert(v.cbegin() + 10, 1); + const int lvalue = 1; + std::vector::iterator i = v.insert(v.cbegin() + 10, lvalue); assert(v.size() == 101); assert(is_contiguous_container_asan_correct(v)); assert(i == v.begin() + 10); @@ -34,11 +35,29 @@ for (++j; j < 101; ++j) assert(v[j] == 0); } + { + const size_t n = 100; + std::vector v(n); + v.reserve(n + 1); + const int lvalue = 1; + + // no reallocation expected + std::vector::iterator it = v.insert(v.cbegin() + n, lvalue); + + assert(v.size() == n + 1); + assert(is_contiguous_container_asan_correct(v)); + assert(it == v.begin() + n); + for (size_t i = 0; i < n; ++i) { + assert(v[i] == 0); + } + assert(v[n] == lvalue); + } { std::vector v(100); while(v.size() < v.capacity()) v.push_back(0); // force reallocation size_t sz = v.size(); - std::vector::iterator i = v.insert(v.cbegin() + 10, 1); + const int lvalue = 1; + std::vector::iterator i = v.insert(v.cbegin() + 10, lvalue); assert(v.size() == sz + 1); assert(is_contiguous_container_asan_correct(v)); assert(i == v.begin() + 10); @@ -54,7 +73,8 @@ while(v.size() < v.capacity()) v.push_back(0); v.pop_back(); v.pop_back(); // force no reallocation size_t sz = v.size(); - std::vector::iterator i = v.insert(v.cbegin() + 10, 1); + const int lvalue = 1; + std::vector::iterator i = v.insert(v.cbegin() + 10, lvalue); assert(v.size() == sz + 1); assert(is_contiguous_container_asan_correct(v)); assert(i == v.begin() + 10); @@ -67,7 +87,8 @@ } { std::vector > v(100); - std::vector >::iterator i = v.insert(v.cbegin() + 10, 1); + const int lvalue = 1; + std::vector >::iterator i = v.insert(v.cbegin() + 10, lvalue); assert(v.size() == 101); assert(is_contiguous_container_asan_correct(v)); assert(i == v.begin() + 10); @@ -81,7 +102,8 @@ #if TEST_STD_VER >= 11 { std::vector> v(100); - std::vector>::iterator i = v.insert(v.cbegin() + 10, 1); + const int lvalue = 1; + std::vector>::iterator i = v.insert(v.cbegin() + 10, lvalue); assert(v.size() == 101); assert(is_contiguous_container_asan_correct(v)); assert(i == v.begin() + 10); Index: libcxx/test/support/allocators.h =================================================================== --- libcxx/test/support/allocators.h +++ libcxx/test/support/allocators.h @@ -185,6 +185,55 @@ return !(x == y); } +template +class MaybePOCCAAllocator { + int id_ = 0; + bool* copy_assigned_into_ = nullptr; +public: + typedef std::integral_constant propagate_on_container_copy_assignment; + typedef T value_type; + + MaybePOCCAAllocator() = default; + MaybePOCCAAllocator(int id, bool* copy_assigned_into) + : id_(id), copy_assigned_into_(copy_assigned_into) {} + + MaybePOCCAAllocator(const MaybePOCCAAllocator&) = default; + MaybePOCCAAllocator& operator=(const MaybePOCCAAllocator& a) + { + id_ = a.id(); + if (copy_assigned_into_) + *copy_assigned_into_ = true; + return *this; + } + + T* allocate(std::size_t n) + { + return static_cast(::operator new(n * sizeof(T))); + } + + void deallocate(T* ptr, std::size_t) + { + ::operator delete(ptr); + } + + int id() const { return id_; } + + friend bool operator==(const MaybePOCCAAllocator& lhs, const MaybePOCCAAllocator& rhs) + { + return lhs.id() == rhs.id(); + } + + friend bool operator!=(const MaybePOCCAAllocator& lhs, const MaybePOCCAAllocator& rhs) + { + return !(lhs == rhs); + } +}; + +template +using POCCAAllocator = MaybePOCCAAllocator; +template +using NonPOCCAAllocator = MaybePOCCAAllocator; + #endif // TEST_STD_VER >= 11 #endif // ALLOCATORS_H