Author: hans Date: Wed Aug 17 19:23:33 2016 New Revision: 279017 URL: http://llvm.org/viewvc/llvm-project?rev=279017&view=rev Log: Merging r279008: ------------------------------------------------------------------------ r279008 | marshall | 2016-08-17 16:24:02 -0700 (Wed, 17 Aug 2016) | 1 line
make the associative containers do the right thing for propogate_on_container_assignment. Fixes bug #29001. Tests are only for <map> right now - more complete tests will come when we revamp our allocator testing structure. ------------------------------------------------------------------------ Modified: libcxx/branches/release_39/ (props changed) libcxx/branches/release_39/include/__tree libcxx/branches/release_39/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp Propchange: libcxx/branches/release_39/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Wed Aug 17 19:23:33 2016 @@ -1,2 +1,2 @@ /libcxx/branches/apple:136569-137939 -/libcxx/trunk:278282,278357,278387,278904 +/libcxx/trunk:278282,278357,278387,278904,279008 Modified: libcxx/branches/release_39/include/__tree URL: http://llvm.org/viewvc/llvm-project/libcxx/branches/release_39/include/__tree?rev=279017&r1=279016&r2=279017&view=diff ============================================================================== --- libcxx/branches/release_39/include/__tree (original) +++ libcxx/branches/release_39/include/__tree Wed Aug 17 19:23:33 2016 @@ -1419,7 +1419,11 @@ private: _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __tree& __t, true_type) - {__node_alloc() = __t.__node_alloc();} + { + if (__node_alloc() != __t.__node_alloc()) + clear(); + __node_alloc() = __t.__node_alloc(); + } _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const __tree& __t, false_type) {} Modified: libcxx/branches/release_39/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/branches/release_39/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp?rev=279017&r1=279016&r2=279017&view=diff ============================================================================== --- libcxx/branches/release_39/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp (original) +++ libcxx/branches/release_39/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp Wed Aug 17 19:23:33 2016 @@ -15,11 +15,99 @@ #include <map> #include <cassert> +#include <vector> +#include <algorithm> + +#include <iostream> #include "../../../test_compare.h" #include "test_allocator.h" #include "min_allocator.h" +#if TEST_STD_VER >= 11 +std::vector<int> ca_allocs; +std::vector<int> ca_deallocs; + +template <class T> +class counting_allocatorT { +public: + typedef T value_type; + int foo{0}; + counting_allocatorT(int f) noexcept : foo(f) {} + + using propagate_on_container_copy_assignment = std::true_type; + template <class U> counting_allocatorT(const counting_allocatorT<U>& other) noexcept {foo = other.foo;} + template <class U> bool operator==(const counting_allocatorT<U>& other) const noexcept { return foo == other.foo; } + template <class U> bool operator!=(const counting_allocatorT<U>& other) const noexcept { return foo != other.foo; } + + T * allocate(const size_t n) const { + ca_allocs.push_back(foo); + void * const pv = ::malloc(n * sizeof(T)); + return static_cast<T *>(pv); + } + void deallocate(T * const p, size_t) const noexcept { + ca_deallocs.push_back(foo); + free(p); + } +}; + +template <class T> +class counting_allocatorF { +public: + typedef T value_type; + int foo{0}; + counting_allocatorF(int f) noexcept : foo(f) {} + + using propagate_on_container_copy_assignment = std::false_type; + template <class U> counting_allocatorF(const counting_allocatorF<U>& other) noexcept {foo = other.foo;} + template <class U> bool operator==(const counting_allocatorF<U>& other) const noexcept { return foo == other.foo; } + template <class U> bool operator!=(const counting_allocatorF<U>& other) const noexcept { return foo != other.foo; } + + T * allocate(const size_t n) const { + ca_allocs.push_back(foo); + void * const pv = ::malloc(n * sizeof(T)); + return static_cast<T *>(pv); + } + void deallocate(T * const p, size_t) const noexcept { + ca_deallocs.push_back(foo); + free(p); + } +}; + +bool balanced_allocs() { + std::vector<int> temp1, temp2; + + std::cout << "Allocations = " << ca_allocs.size() << ", deallocatons = " << ca_deallocs.size() << std::endl; + if (ca_allocs.size() != ca_deallocs.size()) + return false; + + temp1 = ca_allocs; + std::sort(temp1.begin(), temp1.end()); + temp2.clear(); + std::unique_copy(temp1.begin(), temp1.end(), std::back_inserter<std::vector<int>>(temp2)); + std::cout << "There were " << temp2.size() << " different allocators\n"; + + for (std::vector<int>::const_iterator it = temp2.begin(); it != temp2.end(); ++it ) { + std::cout << *it << ": " << std::count(ca_allocs.begin(), ca_allocs.end(), *it) << " vs " << std::count(ca_deallocs.begin(), ca_deallocs.end(), *it) << std::endl; + if ( std::count(ca_allocs.begin(), ca_allocs.end(), *it) != std::count(ca_deallocs.begin(), ca_deallocs.end(), *it)) + return false; + } + + temp1 = ca_allocs; + std::sort(temp1.begin(), temp1.end()); + temp2.clear(); + std::unique_copy(temp1.begin(), temp1.end(), std::back_inserter<std::vector<int>>(temp2)); + std::cout << "There were " << temp2.size() << " different (de)allocators\n"; + for (std::vector<int>::const_iterator it = ca_deallocs.begin(); it != ca_deallocs.end(); ++it ) { + std::cout << *it << ": " << std::count(ca_allocs.begin(), ca_allocs.end(), *it) << " vs " << std::count(ca_deallocs.begin(), ca_deallocs.end(), *it) << std::endl; + if ( std::count(ca_allocs.begin(), ca_allocs.end(), *it) != std::count(ca_deallocs.begin(), ca_deallocs.end(), *it)) + return false; + } + + return true; + } +#endif + int main() { { @@ -178,5 +266,75 @@ int main() assert(*next(mo.begin()) == V(2, 1)); assert(*next(mo.begin(), 2) == V(3, 1)); } + + assert(balanced_allocs()); + { + typedef std::pair<const int, double> V; + V ar[] = + { + V(1, 1), + V(1, 1.5), + V(1, 2), + V(2, 1), + V(2, 1.5), + V(2, 2), + V(3, 1), + V(3, 1.5), + V(3, 2) + }; + typedef test_compare<std::less<int> > C; + typedef counting_allocatorT<V> A; + std::map<int, double, C, A> mo(ar, ar+sizeof(ar)/sizeof(ar[0]), C(5), A(1)); + std::map<int, double, C, A> m(ar, ar+sizeof(ar)/sizeof(ar[0])/2, C(3), A(2)); + m = mo; + assert(m.key_comp() == C(5)); + assert(m.size() == 3); + assert(distance(m.begin(), m.end()) == 3); + assert(*m.begin() == V(1, 1)); + assert(*next(m.begin()) == V(2, 1)); + assert(*next(m.begin(), 2) == V(3, 1)); + + assert(mo.key_comp() == C(5)); + assert(mo.size() == 3); + assert(distance(mo.begin(), mo.end()) == 3); + assert(*mo.begin() == V(1, 1)); + assert(*next(mo.begin()) == V(2, 1)); + assert(*next(mo.begin(), 2) == V(3, 1)); + } + assert(balanced_allocs()); + { + typedef std::pair<const int, double> V; + V ar[] = + { + V(1, 1), + V(1, 1.5), + V(1, 2), + V(2, 1), + V(2, 1.5), + V(2, 2), + V(3, 1), + V(3, 1.5), + V(3, 2) + }; + typedef test_compare<std::less<int> > C; + typedef counting_allocatorF<V> A; + std::map<int, double, C, A> mo(ar, ar+sizeof(ar)/sizeof(ar[0]), C(5), A(100)); + std::map<int, double, C, A> m(ar, ar+sizeof(ar)/sizeof(ar[0])/2, C(3), A(200)); + m = mo; + assert(m.key_comp() == C(5)); + assert(m.size() == 3); + assert(distance(m.begin(), m.end()) == 3); + assert(*m.begin() == V(1, 1)); + assert(*next(m.begin()) == V(2, 1)); + assert(*next(m.begin(), 2) == V(3, 1)); + + assert(mo.key_comp() == C(5)); + assert(mo.size() == 3); + assert(distance(mo.begin(), mo.end()) == 3); + assert(*mo.begin() == V(1, 1)); + assert(*next(mo.begin()) == V(2, 1)); + assert(*next(mo.begin(), 2) == V(3, 1)); + } + assert(balanced_allocs()); #endif } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits