mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-11 11:45:11 +08:00
re PR libstdc++/34595 (std::copy copies the output iterator before assigning)
2007-12-26 Paolo Carlini <pcarlini@suse.de> PR libstdc++/34595 * include/bits/stl_algobase.h (struct __cm_assign): Remove. (struct __copy_move<true, false, _Category>, struct __copy_move<true, false, random_access_iterator_tag>, struct __copy_move_backward<true, false, _Category>, struct __copy_move_backward<true, false, random_access_iterator_tag>): Add. (struct __copy_move, struct __copy_move_backward, struct __copy_move<false, false, random_access_iterator_tag>, struct __copy_move_backward<false, false, random_access_iterator_tag>): Adjust. * testsuite/25_algorithms/copy/34595.C: New. From-SVN: r131188
This commit is contained in:
parent
3dfb41c564
commit
5f6d5f0af6
@ -1,3 +1,18 @@
|
||||
2007-12-26 Paolo Carlini <pcarlini@suse.de>
|
||||
|
||||
PR libstdc++/34595
|
||||
* include/bits/stl_algobase.h (struct __cm_assign): Remove.
|
||||
(struct __copy_move<true, false, _Category>,
|
||||
struct __copy_move<true, false, random_access_iterator_tag>,
|
||||
struct __copy_move_backward<true, false, _Category>,
|
||||
struct __copy_move_backward<true, false, random_access_iterator_tag>):
|
||||
Add.
|
||||
(struct __copy_move, struct __copy_move_backward,
|
||||
struct __copy_move<false, false, random_access_iterator_tag>,
|
||||
struct __copy_move_backward<false, false, random_access_iterator_tag>):
|
||||
Adjust.
|
||||
* testsuite/25_algorithms/copy/34595.C: New.
|
||||
|
||||
2007-12-26 Chris Fairles <chris.fairles@gmail.com>
|
||||
Paolo Carlini <pcarlini@suse.de>
|
||||
|
||||
|
@ -295,34 +295,13 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
{ return __it.base(); }
|
||||
};
|
||||
|
||||
// Used in __copy_move and __copy_move_backward below.
|
||||
template<bool _IsMove>
|
||||
struct __cm_assign
|
||||
{
|
||||
template<typename _IteratorL, typename _IteratorR>
|
||||
static void
|
||||
__a(_IteratorL __lhs, _IteratorR __rhs)
|
||||
{ *__lhs = *__rhs; }
|
||||
};
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
template<>
|
||||
struct __cm_assign<true>
|
||||
{
|
||||
template<typename _IteratorL, typename _IteratorR>
|
||||
static void
|
||||
__a(_IteratorL __lhs, _IteratorR __rhs)
|
||||
{ *__lhs = std::move(*__rhs); }
|
||||
};
|
||||
#endif
|
||||
|
||||
// All of these auxiliary structs serve two purposes. (1) Replace
|
||||
// calls to copy with memmove whenever possible. (Memmove, not memcpy,
|
||||
// because the input and output ranges are permitted to overlap.)
|
||||
// (2) If we're using random access iterators, then write the loop as
|
||||
// a for loop with an explicit count.
|
||||
|
||||
template<bool _IsMove, bool, typename>
|
||||
template<bool, bool, typename>
|
||||
struct __copy_move
|
||||
{
|
||||
template<typename _II, typename _OI>
|
||||
@ -330,13 +309,28 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
__copy_m(_II __first, _II __last, _OI __result)
|
||||
{
|
||||
for (; __first != __last; ++__result, ++__first)
|
||||
std::__cm_assign<_IsMove>::__a(__result, __first);
|
||||
*__result = *__first;
|
||||
return __result;
|
||||
}
|
||||
};
|
||||
|
||||
template<bool _IsMove, bool _IsSimple>
|
||||
struct __copy_move<_IsMove, _IsSimple, random_access_iterator_tag>
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
template<typename _Category>
|
||||
struct __copy_move<true, false, _Category>
|
||||
{
|
||||
template<typename _II, typename _OI>
|
||||
static _OI
|
||||
__copy_m(_II __first, _II __last, _OI __result)
|
||||
{
|
||||
for (; __first != __last; ++__result, ++__first)
|
||||
*__result = std::move(*__first);
|
||||
return __result;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<>
|
||||
struct __copy_move<false, false, random_access_iterator_tag>
|
||||
{
|
||||
template<typename _II, typename _OI>
|
||||
static _OI
|
||||
@ -345,7 +339,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
typedef typename iterator_traits<_II>::difference_type _Distance;
|
||||
for(_Distance __n = __last - __first; __n > 0; --__n)
|
||||
{
|
||||
std::__cm_assign<_IsMove>::__a(__result, __first);
|
||||
*__result = *__first;
|
||||
++__first;
|
||||
++__result;
|
||||
}
|
||||
@ -353,6 +347,26 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
template<>
|
||||
struct __copy_move<true, false, random_access_iterator_tag>
|
||||
{
|
||||
template<typename _II, typename _OI>
|
||||
static _OI
|
||||
__copy_m(_II __first, _II __last, _OI __result)
|
||||
{
|
||||
typedef typename iterator_traits<_II>::difference_type _Distance;
|
||||
for(_Distance __n = __last - __first; __n > 0; --__n)
|
||||
{
|
||||
*__result = std::move(*__first);
|
||||
++__first;
|
||||
++__result;
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<bool _IsMove>
|
||||
struct __copy_move<_IsMove, true, random_access_iterator_tag>
|
||||
{
|
||||
@ -489,7 +503,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
#define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::copy(_Tp, _Up, _Vp)
|
||||
#endif
|
||||
|
||||
template<bool _IsMove, bool, typename>
|
||||
template<bool, bool, typename>
|
||||
struct __copy_move_backward
|
||||
{
|
||||
template<typename _BI1, typename _BI2>
|
||||
@ -497,13 +511,28 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result)
|
||||
{
|
||||
while (__first != __last)
|
||||
std::__cm_assign<_IsMove>::__a(--__result, --__last);
|
||||
*--__result = *--__last;
|
||||
return __result;
|
||||
}
|
||||
};
|
||||
|
||||
template<bool _IsMove, bool _IsSimple>
|
||||
struct __copy_move_backward<_IsMove, _IsSimple, random_access_iterator_tag>
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
template<typename _Category>
|
||||
struct __copy_move_backward<true, false, _Category>
|
||||
{
|
||||
template<typename _BI1, typename _BI2>
|
||||
static _BI2
|
||||
__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result)
|
||||
{
|
||||
while (__first != __last)
|
||||
*--__result = std::move(*--__last);
|
||||
return __result;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<>
|
||||
struct __copy_move_backward<false, false, random_access_iterator_tag>
|
||||
{
|
||||
template<typename _BI1, typename _BI2>
|
||||
static _BI2
|
||||
@ -511,11 +540,27 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
||||
{
|
||||
typename iterator_traits<_BI1>::difference_type __n;
|
||||
for (__n = __last - __first; __n > 0; --__n)
|
||||
std::__cm_assign<_IsMove>::__a(--__result, --__last);
|
||||
*--__result = *--__last;
|
||||
return __result;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
template<>
|
||||
struct __copy_move_backward<true, false, random_access_iterator_tag>
|
||||
{
|
||||
template<typename _BI1, typename _BI2>
|
||||
static _BI2
|
||||
__copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result)
|
||||
{
|
||||
typename iterator_traits<_BI1>::difference_type __n;
|
||||
for (__n = __last - __first; __n > 0; --__n)
|
||||
*--__result = std::move(*--__last);
|
||||
return __result;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template<bool _IsMove>
|
||||
struct __copy_move_backward<_IsMove, true, random_access_iterator_tag>
|
||||
{
|
||||
|
55
libstdc++-v3/testsuite/25_algorithms/copy/34595.C
Normal file
55
libstdc++-v3/testsuite/25_algorithms/copy/34595.C
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2007 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 2, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without Pred 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 COPYING. If not, write to the Free
|
||||
// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
// USA.
|
||||
|
||||
// 25.2.1 [lib.alg.copy] Copy.
|
||||
|
||||
#include <algorithm>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
class Counting_output_iterator
|
||||
: public std::iterator< std::output_iterator_tag, void, void, void, void >
|
||||
{
|
||||
std::size_t c;
|
||||
public:
|
||||
Counting_output_iterator() : c(0) {}
|
||||
Counting_output_iterator& operator++() { return *this; }
|
||||
Counting_output_iterator& operator*() { return *this; }
|
||||
|
||||
template <typename T>
|
||||
void operator=(const T&) { ++c; }
|
||||
|
||||
std::size_t current_counter() const { return c; }
|
||||
};
|
||||
|
||||
// libstdc++/34595
|
||||
void test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = true;
|
||||
|
||||
int t[10] = {0,};
|
||||
Counting_output_iterator cnt;
|
||||
std::size_t res = std::copy(t+0, t+5, cnt).current_counter();
|
||||
|
||||
VERIFY( res == 5 );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user