diff options
author | Paolo Carlini <paolo.carlini@oracle.com> | 2011-07-11 18:38:54 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2011-07-11 18:38:54 +0000 |
commit | 848ca96f30746fc6972105de156656ce8c5ee586 (patch) | |
tree | af254038a743c9a107aed7a037726e84595e5ec9 | |
parent | f9610d205a723ac0d4cb4076dbd2d935b0077373 (diff) | |
download | gcc-848ca96f30746fc6972105de156656ce8c5ee586.zip gcc-848ca96f30746fc6972105de156656ce8c5ee586.tar.gz gcc-848ca96f30746fc6972105de156656ce8c5ee586.tar.bz2 |
re PR libstdc++/49559 ([C++0x] stable_sort calls self-move-assignment operator)
2011-07-11 Paolo Carlini <paolo.carlini@oracle.com>
PR libstdc++/49559
* include/bits/stl_algo.h (__move_merge_backward): Remove.
(__move_merge_adaptive, __move_merge_adaptive_backward): New.
(__merge_adaptive): Use the latter two.
(__rotate_adaptive): Avoid self move-assignment.
* include/bits/stl_algobase.h (move_backward): Fix comment.
* testsuite/25_algorithms/stable_sort/49559.cc: New.
* testsuite/25_algorithms/inplace_merge/49559.cc: Likewise.
* testsuite/25_algorithms/inplace_merge/moveable.cc: Extend.
* testsuite/25_algorithms/inplace_merge/moveable2.cc: Likewise.
* testsuite/util/testsuite_rvalref.h (rvalstruct::operator=
(rvalstruct&&)): Check for self move-assignment.
From-SVN: r176174
-rw-r--r-- | libstdc++-v3/ChangeLog | 15 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/stl_algo.h | 263 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/stl_algobase.h | 2 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/25_algorithms/inplace_merge/49559.cc | 72 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/25_algorithms/inplace_merge/moveable.cc | 60 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/25_algorithms/inplace_merge/moveable2.cc | 62 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/25_algorithms/stable_sort/49559.cc | 68 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/util/testsuite_rvalref.h | 1 |
8 files changed, 434 insertions, 109 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7ec671c..e628417 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,20 @@ 2011-07-11 Paolo Carlini <paolo.carlini@oracle.com> + PR libstdc++/49559 + * include/bits/stl_algo.h (__move_merge_backward): Remove. + (__move_merge_adaptive, __move_merge_adaptive_backward): New. + (__merge_adaptive): Use the latter two. + (__rotate_adaptive): Avoid self move-assignment. + * include/bits/stl_algobase.h (move_backward): Fix comment. + * testsuite/25_algorithms/stable_sort/49559.cc: New. + * testsuite/25_algorithms/inplace_merge/49559.cc: Likewise. + * testsuite/25_algorithms/inplace_merge/moveable.cc: Extend. + * testsuite/25_algorithms/inplace_merge/moveable2.cc: Likewise. + * testsuite/util/testsuite_rvalref.h (rvalstruct::operator= + (rvalstruct&&)): Check for self move-assignment. + +2011-07-11 Paolo Carlini <paolo.carlini@oracle.com> + * testsuite/util/testsuite_allocator.h (propagating_allocator<>:: operator=(const propagating_allocator<>&)): Retun *this. diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index 5fc561e..8391d3e 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -2716,20 +2716,76 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // merge - /// This is a helper function for the merge routines. + /// This is a helper function for the __merge_adaptive routines. + template<typename _InputIterator1, typename _InputIterator2, + typename _OutputIterator> + void + __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (*__first2 < *__first1) + { + *__result = _GLIBCXX_MOVE(*__first2); + ++__first2; + } + else + { + *__result = _GLIBCXX_MOVE(*__first1); + ++__first1; + } + ++__result; + } + if (__first1 != __last1) + _GLIBCXX_MOVE3(__first1, __last1, __result); + } + + /// This is a helper function for the __merge_adaptive routines. + template<typename _InputIterator1, typename _InputIterator2, + typename _OutputIterator, typename _Compare> + void + __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(*__first2, *__first1)) + { + *__result = _GLIBCXX_MOVE(*__first2); + ++__first2; + } + else + { + *__result = _GLIBCXX_MOVE(*__first1); + ++__first1; + } + ++__result; + } + if (__first1 != __last1) + _GLIBCXX_MOVE3(__first1, __last1, __result); + } + + /// This is a helper function for the __merge_adaptive routines. template<typename _BidirectionalIterator1, typename _BidirectionalIterator2, typename _BidirectionalIterator3> - _BidirectionalIterator3 - __move_merge_backward(_BidirectionalIterator1 __first1, - _BidirectionalIterator1 __last1, - _BidirectionalIterator2 __first2, - _BidirectionalIterator2 __last2, - _BidirectionalIterator3 __result) + void + __move_merge_adaptive_backward(_BidirectionalIterator1 __first1, + _BidirectionalIterator1 __last1, + _BidirectionalIterator2 __first2, + _BidirectionalIterator2 __last2, + _BidirectionalIterator3 __result) { if (__first1 == __last1) - return _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result); - if (__first2 == __last2) - return _GLIBCXX_MOVE_BACKWARD3(__first1, __last1, __result); + { + _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result); + return; + } + else if (__first2 == __last2) + return; + --__last1; --__last2; while (true) @@ -2738,34 +2794,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { *--__result = _GLIBCXX_MOVE(*__last1); if (__first1 == __last1) - return _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result); + { + _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result); + return; + } --__last1; } else { *--__result = _GLIBCXX_MOVE(*__last2); if (__first2 == __last2) - return _GLIBCXX_MOVE_BACKWARD3(__first1, ++__last1, __result); + return; --__last2; } } } - /// This is a helper function for the merge routines. + /// This is a helper function for the __merge_adaptive routines. template<typename _BidirectionalIterator1, typename _BidirectionalIterator2, typename _BidirectionalIterator3, typename _Compare> - _BidirectionalIterator3 - __move_merge_backward(_BidirectionalIterator1 __first1, - _BidirectionalIterator1 __last1, - _BidirectionalIterator2 __first2, - _BidirectionalIterator2 __last2, - _BidirectionalIterator3 __result, - _Compare __comp) + void + __move_merge_adaptive_backward(_BidirectionalIterator1 __first1, + _BidirectionalIterator1 __last1, + _BidirectionalIterator2 __first2, + _BidirectionalIterator2 __last2, + _BidirectionalIterator3 __result, + _Compare __comp) { if (__first1 == __last1) - return _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result); - if (__first2 == __last2) - return _GLIBCXX_MOVE_BACKWARD3(__first1, __last1, __result); + { + _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result); + return; + } + else if (__first2 == __last2) + return; + --__last1; --__last2; while (true) @@ -2774,75 +2837,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { *--__result = _GLIBCXX_MOVE(*__last1); if (__first1 == __last1) - return _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result); + { + _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result); + return; + } --__last1; } else { *--__result = _GLIBCXX_MOVE(*__last2); if (__first2 == __last2) - return _GLIBCXX_MOVE_BACKWARD3(__first1, ++__last1, __result); + return; --__last2; } } } /// This is a helper function for the merge routines. - template<typename _InputIterator1, typename _InputIterator2, - typename _OutputIterator> - _OutputIterator - __move_merge(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result) - { - while (__first1 != __last1 && __first2 != __last2) - { - if (*__first2 < *__first1) - { - *__result = _GLIBCXX_MOVE(*__first2); - ++__first2; - } - else - { - *__result = _GLIBCXX_MOVE(*__first1); - ++__first1; - } - ++__result; - } - return _GLIBCXX_MOVE3(__first2, __last2, - _GLIBCXX_MOVE3(__first1, __last1, - __result)); - } - - /// This is a helper function for the merge routines. - template<typename _InputIterator1, typename _InputIterator2, - typename _OutputIterator, typename _Compare> - _OutputIterator - __move_merge(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, _Compare __comp) - { - while (__first1 != __last1 && __first2 != __last2) - { - if (__comp(*__first2, *__first1)) - { - *__result = _GLIBCXX_MOVE(*__first2); - ++__first2; - } - else - { - *__result = _GLIBCXX_MOVE(*__first1); - ++__first1; - } - ++__result; - } - return _GLIBCXX_MOVE3(__first2, __last2, - _GLIBCXX_MOVE3(__first1, __last1, - __result)); - } - - - /// This is a helper function for the merge routines. template<typename _BidirectionalIterator1, typename _BidirectionalIterator2, typename _Distance> _BidirectionalIterator1 @@ -2856,15 +2867,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _BidirectionalIterator2 __buffer_end; if (__len1 > __len2 && __len2 <= __buffer_size) { - __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); - _GLIBCXX_MOVE_BACKWARD3(__first, __middle, __last); - return _GLIBCXX_MOVE3(__buffer, __buffer_end, __first); + if (__len2) + { + __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); + _GLIBCXX_MOVE_BACKWARD3(__first, __middle, __last); + return _GLIBCXX_MOVE3(__buffer, __buffer_end, __first); + } + else + return __first; } else if (__len1 <= __buffer_size) { - __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); - _GLIBCXX_MOVE3(__middle, __last, __first); - return _GLIBCXX_MOVE_BACKWARD3(__buffer, __buffer_end, __last); + if (__len1) + { + __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); + _GLIBCXX_MOVE3(__middle, __last, __first); + return _GLIBCXX_MOVE_BACKWARD3(__buffer, __buffer_end, __last); + } + else + return __last; } else { @@ -2887,13 +2908,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__len1 <= __len2 && __len1 <= __buffer_size) { _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); - std::__move_merge(__buffer, __buffer_end, __middle, __last, __first); + std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last, + __first); } else if (__len2 <= __buffer_size) { _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); - std::__move_merge_backward(__first, __middle, __buffer, - __buffer_end, __last); + std::__move_merge_adaptive_backward(__first, __middle, __buffer, + __buffer_end, __last); } else { @@ -2943,14 +2965,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__len1 <= __len2 && __len1 <= __buffer_size) { _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); - std::__move_merge(__buffer, __buffer_end, __middle, __last, - __first, __comp); + std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last, + __first, __comp); } else if (__len2 <= __buffer_size) { _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); - std::__move_merge_backward(__first, __middle, __buffer, __buffer_end, - __last, __comp); + std::__move_merge_adaptive_backward(__first, __middle, __buffer, + __buffer_end, __last, __comp); } else { @@ -3187,6 +3209,61 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __comp); } + + /// This is a helper function for the __merge_sort_loop routines. + template<typename _InputIterator1, typename _InputIterator2, + typename _OutputIterator> + _OutputIterator + __move_merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (*__first2 < *__first1) + { + *__result = _GLIBCXX_MOVE(*__first2); + ++__first2; + } + else + { + *__result = _GLIBCXX_MOVE(*__first1); + ++__first1; + } + ++__result; + } + return _GLIBCXX_MOVE3(__first2, __last2, + _GLIBCXX_MOVE3(__first1, __last1, + __result)); + } + + /// This is a helper function for the __merge_sort_loop routines. + template<typename _InputIterator1, typename _InputIterator2, + typename _OutputIterator, typename _Compare> + _OutputIterator + __move_merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(*__first2, *__first1)) + { + *__result = _GLIBCXX_MOVE(*__first2); + ++__first2; + } + else + { + *__result = _GLIBCXX_MOVE(*__first1); + ++__first1; + } + ++__result; + } + return _GLIBCXX_MOVE3(__first2, __last2, + _GLIBCXX_MOVE3(__first1, __last1, + __result)); + } + template<typename _RandomAccessIterator1, typename _RandomAccessIterator2, typename _Distance> void diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index 626d5bf..aecdcb9 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -641,7 +641,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * loop count will be known (and therefore a candidate for compiler * optimizations such as unrolling). * - * Result may not be in the range [first,last). Use move instead. Note + * Result may not be in the range (first,last]. Use move instead. Note * that the start of the output range may overlap [first,last). */ template<typename _BI1, typename _BI2> diff --git a/libstdc++-v3/testsuite/25_algorithms/inplace_merge/49559.cc b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/49559.cc new file mode 100644 index 0000000..8b7b52e --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/49559.cc @@ -0,0 +1,72 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#undef _GLIBCXX_CONCEPT_CHECKS + +// XXX FIXME: parallel-mode should deal correctly with moveable-only types +// per C++0x, at minimum smoothly fall back to serial. +#undef _GLIBCXX_PARALLEL + +#include <algorithm> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> +#include <testsuite_rvalref.h> + +using __gnu_test::test_container; +using __gnu_test::bidirectional_iterator_wrapper; +using __gnu_test::rvalstruct; + +typedef test_container<rvalstruct, bidirectional_iterator_wrapper> Container; + +const int A[] = { 0, 1, 2, 3, 4, 5 }; +const int N = 6; + +bool are_ordered(const rvalstruct& lhs, const rvalstruct& rhs) +{ return lhs < rhs; } + +// libstdc++/49559 +void test01() +{ + bool test __attribute__((unused)) = true; + + rvalstruct s1[6]; + std::copy(A, A + N, s1); + Container con1(s1, s1 + N); + std::inplace_merge(con1.begin(), con1.it(4), con1.end()); + VERIFY( s1[0] == 0 && s1[1] == 1 && s1[2] == 2 + && s1[3] == 3 && s1[4] == 4 && s1[5] == 5 ); + VERIFY( s1[0].valid && s1[1].valid && s1[2].valid + && s1[3].valid && s1[4].valid && s1[5].valid ); + + rvalstruct s2[6]; + std::copy(A, A + N, s2); + Container con2(s2, s2 + N); + std::inplace_merge(con2.begin(), con2.it(4), con2.end(), are_ordered); + VERIFY( s2[0] == 0 && s2[1] == 1 && s2[2] == 2 + && s2[3] == 3 && s2[4] == 4 && s2[5] == 5 ); + VERIFY( s2[0].valid && s2[1].valid && s2[2].valid + && s2[3].valid && s2[4].valid && s2[5].valid ); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/25_algorithms/inplace_merge/moveable.cc b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/moveable.cc index 00ae7f2..7d14c29 100644 --- a/libstdc++-v3/testsuite/25_algorithms/inplace_merge/moveable.cc +++ b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/moveable.cc @@ -35,13 +35,59 @@ test01() { bool test __attribute__((unused)) = true; - int array[]={0,2,4,1,3,5}; - rvalstruct rv_array[6]; - std::copy(array, array + 6, rv_array); - container con(rv_array, rv_array + 6); - std::inplace_merge(con.begin(), con.it(3), con.end()); - VERIFY( rv_array[0] == 0 && rv_array[1] == 1 && rv_array[2] == 2 - && rv_array[3] == 3 && rv_array[4] == 4 && rv_array[5] == 5 ); + int array1[]={0,2,4,1,3,5}; + rvalstruct rv_array1[6]; + std::copy(array1, array1 + 6, rv_array1); + container con1(rv_array1, rv_array1 + 6); + std::inplace_merge(con1.begin(), con1.it(3), con1.end()); + VERIFY( rv_array1[0] == 0 && rv_array1[1] == 1 && rv_array1[2] == 2 + && rv_array1[3] == 3 && rv_array1[4] == 4 && rv_array1[5] == 5 ); + + int array2[]={0,2,4,5,1,3}; + rvalstruct rv_array2[6]; + std::copy(array2, array2 + 6, rv_array2); + container con2(rv_array2, rv_array2 + 6); + std::inplace_merge(con2.begin(), con2.it(4), con2.end()); + VERIFY( rv_array2[0] == 0 && rv_array2[1] == 1 && rv_array2[2] == 2 + && rv_array2[3] == 3 && rv_array2[4] == 4 && rv_array2[5] == 5 ); + + int array3[]={1,1,1,2,2,2}; + rvalstruct rv_array3[6]; + std::copy(array3, array3 + 6, rv_array3); + container con3(rv_array3, rv_array3 + 6); + std::inplace_merge(con3.begin(), con3.it(3), con3.end()); + VERIFY( rv_array3[0] == 1 && rv_array3[1] == 1 && rv_array3[2] == 1 + && rv_array3[3] == 2 && rv_array3[4] == 2 && rv_array3[5] == 2 ); + + int array4[]={1,1,1,1,2,2}; + rvalstruct rv_array4[6]; + std::copy(array4, array4 + 6, rv_array4); + container con4(rv_array4, rv_array4 + 6); + std::inplace_merge(con4.begin(), con4.it(4), con4.end()); + VERIFY( rv_array4[0] == 1 && rv_array4[1] == 1 && rv_array4[2] == 1 + && rv_array4[3] == 1 && rv_array4[4] == 2 && rv_array4[5] == 2 ); + + int array5[]={3,3,3,3}; + rvalstruct rv_array5[4]; + std::copy(array5, array5 + 4, rv_array5); + container con5(rv_array5, rv_array5 + 4); + std::inplace_merge(con5.begin(), con5.it(2), con5.end()); + VERIFY( rv_array5[0] == 3 && rv_array5[1] == 3 && rv_array5[2] == 3 + && rv_array5[3] == 3 ); + + int array6[]={3,3,3}; + rvalstruct rv_array6[3]; + std::copy(array6, array6 + 3, rv_array6); + container con6(rv_array6, rv_array6 + 3); + std::inplace_merge(con6.begin(), con6.it(0), con6.end()); + VERIFY( rv_array6[0] == 3 && rv_array6[1] == 3 && rv_array6[2] == 3 ); + + int array7[]={3,3}; + rvalstruct rv_array7[2]; + std::copy(array7, array7 + 2, rv_array7); + container con7(rv_array7, rv_array7 + 2); + std::inplace_merge(con7.begin(), con7.it(2), con7.end()); + VERIFY( rv_array7[0] == 3 && rv_array7[1] == 3 ); } int diff --git a/libstdc++-v3/testsuite/25_algorithms/inplace_merge/moveable2.cc b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/moveable2.cc index 32ab3c7..a3a898c 100644 --- a/libstdc++-v3/testsuite/25_algorithms/inplace_merge/moveable2.cc +++ b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/moveable2.cc @@ -1,6 +1,6 @@ // { dg-options "-std=gnu++0x" } -// Copyright (C) 2009 Free Software Foundation, Inc. +// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -39,13 +39,59 @@ test01() { bool test __attribute__((unused)) = true; - int array[]={0,2,4,1,3,5}; - rvalstruct rv_array[6]; - std::copy(array, array + 6, rv_array); - container con(rv_array, rv_array + 6); - std::inplace_merge(con.begin(), con.it(3), con.end(), are_ordered); - VERIFY( rv_array[0] == 0 && rv_array[1] == 1 && rv_array[2] == 2 - && rv_array[3] == 3 && rv_array[4] == 4 && rv_array[5] == 5 ); + int array1[]={0,2,4,1,3,5}; + rvalstruct rv_array1[6]; + std::copy(array1, array1 + 6, rv_array1); + container con1(rv_array1, rv_array1 + 6); + std::inplace_merge(con1.begin(), con1.it(3), con1.end(), are_ordered); + VERIFY( rv_array1[0] == 0 && rv_array1[1] == 1 && rv_array1[2] == 2 + && rv_array1[3] == 3 && rv_array1[4] == 4 && rv_array1[5] == 5 ); + + int array2[]={0,2,4,5,1,3}; + rvalstruct rv_array2[6]; + std::copy(array2, array2 + 6, rv_array2); + container con2(rv_array2, rv_array2 + 6); + std::inplace_merge(con2.begin(), con2.it(4), con2.end(), are_ordered); + VERIFY( rv_array2[0] == 0 && rv_array2[1] == 1 && rv_array2[2] == 2 + && rv_array2[3] == 3 && rv_array2[4] == 4 && rv_array2[5] == 5 ); + + int array3[]={1,1,1,2,2,2}; + rvalstruct rv_array3[6]; + std::copy(array3, array3 + 6, rv_array3); + container con3(rv_array3, rv_array3 + 6); + std::inplace_merge(con3.begin(), con3.it(3), con3.end(), are_ordered); + VERIFY( rv_array3[0] == 1 && rv_array3[1] == 1 && rv_array3[2] == 1 + && rv_array3[3] == 2 && rv_array3[4] == 2 && rv_array3[5] == 2 ); + + int array4[]={1,1,1,1,2,2}; + rvalstruct rv_array4[6]; + std::copy(array4, array4 + 6, rv_array4); + container con4(rv_array4, rv_array4 + 6); + std::inplace_merge(con4.begin(), con4.it(4), con4.end(), are_ordered); + VERIFY( rv_array4[0] == 1 && rv_array4[1] == 1 && rv_array4[2] == 1 + && rv_array4[3] == 1 && rv_array4[4] == 2 && rv_array4[5] == 2 ); + + int array5[]={3,3,3,3}; + rvalstruct rv_array5[4]; + std::copy(array5, array5 + 4, rv_array5); + container con5(rv_array5, rv_array5 + 4); + std::inplace_merge(con5.begin(), con5.it(2), con5.end(), are_ordered); + VERIFY( rv_array5[0] == 3 && rv_array5[1] == 3 && rv_array5[2] == 3 + && rv_array5[3] == 3 ); + + int array6[]={3,3,3}; + rvalstruct rv_array6[3]; + std::copy(array6, array6 + 3, rv_array6); + container con6(rv_array6, rv_array6 + 3); + std::inplace_merge(con6.begin(), con6.it(0), con6.end(), are_ordered); + VERIFY( rv_array6[0] == 3 && rv_array6[1] == 3 && rv_array6[2] == 3 ); + + int array7[]={3,3}; + rvalstruct rv_array7[2]; + std::copy(array7, array7 + 2, rv_array7); + container con7(rv_array7, rv_array7 + 2); + std::inplace_merge(con7.begin(), con7.it(2), con7.end(), are_ordered); + VERIFY( rv_array7[0] == 3 && rv_array7[1] == 3 ); } int diff --git a/libstdc++-v3/testsuite/25_algorithms/stable_sort/49559.cc b/libstdc++-v3/testsuite/25_algorithms/stable_sort/49559.cc new file mode 100644 index 0000000..5445117 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/stable_sort/49559.cc @@ -0,0 +1,68 @@ +// { dg-options "-std=gnu++0x" } + +// Copyright (C) 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#undef _GLIBCXX_CONCEPT_CHECKS + +// XXX FIXME: parallel-mode should deal correctly with moveable-only types +// per C++0x, at minimum smoothly fall back to serial. +#undef _GLIBCXX_PARALLEL + +#include <algorithm> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> +#include <testsuite_rvalref.h> + +using __gnu_test::test_container; +using __gnu_test::random_access_iterator_wrapper; +using __gnu_test::rvalstruct; + +typedef test_container<rvalstruct, random_access_iterator_wrapper> Container; + +const int A[] = { 10 }; +const int N = 1; + +bool order(const rvalstruct& lhs, const rvalstruct& rhs) +{ return lhs < rhs; } + +// libstdc++/49559 +void test01() +{ + bool test __attribute__((unused)) = true; + + rvalstruct s1[1]; + std::copy(A, A + 1, s1); + Container con1(s1, s1 + 1); + std::stable_sort(con1.begin(), con1.end()); + VERIFY( s1[0] == 10 ); + VERIFY( s1[0].valid ); + + rvalstruct s2[1]; + std::copy(A, A + 1, s2); + Container con2(s2, s2 + 1); + std::stable_sort(con2.begin(), con2.end(), order); + VERIFY( s2[0] == 10 ); + VERIFY( s2[0].valid ); +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/util/testsuite_rvalref.h b/libstdc++-v3/testsuite/util/testsuite_rvalref.h index 3159915..2234e81 100644 --- a/libstdc++-v3/testsuite/util/testsuite_rvalref.h +++ b/libstdc++-v3/testsuite/util/testsuite_rvalref.h @@ -68,6 +68,7 @@ namespace __gnu_test operator=(rvalstruct&& in) { bool test __attribute__((unused)) = true; + VERIFY( this != &in ); VERIFY( in.valid == true ); val = in.val; in.valid = false; |