@@ -34,8 +34,8 @@
// _Iter_base
#include <bits/cpp_type_traits.h> // for __is_integer
#include <bits/move.h> // for __addressof and addressof
+# include <bits/stl_function.h> // for less
#if __cplusplus >= 201103L
-# include <bits/stl_function.h> // for less and greater_equal
# include <type_traits> // for is_lvalue_reference and __and_
#endif
#include <debug/formatter.h>
@@ -52,6 +52,9 @@ namespace __gnu_debug
struct _Insert_range_from_self_is_safe
{ enum { __value = 0 }; };
+ template<typename _Sequence>
+ struct _Is_contiguous_sequence : std::__false_type { };
+
// An arbitrary iterator pointer is not singular.
inline bool
__check_singular_aux(const void*) { return false; }
@@ -175,123 +178,112 @@ namespace __gnu_debug
return __first;
}
-#if __cplusplus >= 201103L
- // Default implementation.
+ /* Handle the case where __other is a pointer to _Sequence::value_type. */
template<typename _Iterator, typename _Sequence>
inline bool
__foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>& __it,
- typename _Sequence::const_pointer __begin,
- typename _Sequence::const_pointer __other)
+ const typename _Sequence::value_type* __other)
{
- typedef typename _Sequence::const_pointer _PointerType;
- constexpr std::less<_PointerType> __l{};
+ typedef const typename _Sequence::value_type* _PointerType;
+ typedef std::less<_PointerType> _Less;
+#if __cplusplus >= 201103L
+ constexpr _Less __l{};
+#else
+ const _Less __l = _Less();
+#endif
+ const _Sequence* __seq = __it._M_get_sequence();
+ const _PointerType __begin = std::__addressof(*__seq->_M_base().begin());
+ const _PointerType __end = std::__addressof(*(__seq->_M_base().end()-1));
- return (__l(__other, __begin)
- || __l(std::addressof(*(__it._M_get_sequence()->_M_base().end()
- - 1)), __other));
+ // Check whether __other points within the contiguous storage.
+ return __l(__other, __begin) || __l(__end, __other);
}
- // Fallback when address type cannot be implicitely casted to sequence
- // const_pointer.
- template<typename _Iterator, typename _Sequence,
- typename _InputIterator>
+ /* Fallback overload for when we can't tell, assume it is valid. */
+ template<typename _Iterator, typename _Sequence>
inline bool
- __foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>&,
- _InputIterator, ...)
+ __foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>&, ...)
{ return true; }
+ /* Handle sequences with contiguous storage */
template<typename _Iterator, typename _Sequence, typename _InputIterator>
inline bool
__foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>& __it,
- _InputIterator __other,
- std::true_type)
+ const _InputIterator& __other,
+ const _InputIterator& __other_end,
+ std::__true_type)
{
- // Only containers with all elements in contiguous memory can have their
- // elements passed through pointers.
- // Arithmetics is here just to make sure we are not dereferencing
- // past-the-end iterator.
- if (__it._M_get_sequence()->_M_base().begin()
- != __it._M_get_sequence()->_M_base().end())
- if (std::addressof(*(__it._M_get_sequence()->_M_base().end() - 1))
- - std::addressof(*(__it._M_get_sequence()->_M_base().begin()))
- == __it._M_get_sequence()->size() - 1)
- return (__foreign_iterator_aux4
- (__it,
- std::addressof(*(__it._M_get_sequence()->_M_base().begin())),
- std::addressof(*__other)));
- return true;
+ if (__other == __other_end)
+ return true; // inserting nothing is safe even if not foreign iters
+ if (__it._M_get_sequence()->begin() == __it._M_get_sequence()->end())
+ return true; // can't be self-inserting if self is empty
+ return __foreign_iterator_aux4(__it, std::__addressof(*__other));
}
-
- /* Fallback overload for which we can't say, assume it is valid. */
+
+ /* Handle non-contiguous containers, assume it is valid. */
template<typename _Iterator, typename _Sequence, typename _InputIterator>
inline bool
- __foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>& __it,
- _InputIterator __other,
- std::false_type)
+ __foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>&,
+ const _InputIterator&, const _InputIterator&,
+ std::__false_type)
{ return true; }
-#endif
- /** Checks that iterators do not belong to the same sequence. */
+ /** Handle debug iterators from the same type of container. */
template<typename _Iterator, typename _Sequence, typename _OtherIterator>
inline bool
__foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
const _Safe_iterator<_OtherIterator, _Sequence>& __other,
- std::input_iterator_tag)
+ const _Safe_iterator<_OtherIterator, _Sequence>&)
{ return __it._M_get_sequence() != __other._M_get_sequence(); }
-
-#if __cplusplus >= 201103L
- /* This overload detects when passing pointers to the contained elements
- rather than using iterators.
- */
+
+ /** Handle debug iterators from different types of container. */
+ template<typename _Iterator, typename _Sequence, typename _OtherIterator,
+ typename _OtherSequence>
+ inline bool
+ __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
+ const _Safe_iterator<_OtherIterator, _OtherSequence>&,
+ const _Safe_iterator<_OtherIterator, _OtherSequence>&)
+ { return true; }
+
+ /* Handle non-debug iterators. */
template<typename _Iterator, typename _Sequence, typename _InputIterator>
inline bool
__foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
- _InputIterator __other,
- std::random_access_iterator_tag)
+ const _InputIterator& __other,
+ const _InputIterator& __other_end)
{
- typedef typename _Sequence::const_iterator _ItType;
- typedef typename std::iterator_traits<_ItType>::reference _Ref;
- return __foreign_iterator_aux3(__it, __other,
- std::is_lvalue_reference<_Ref>());
+ return __foreign_iterator_aux3(__it, __other, __other_end,
+ _Is_contiguous_sequence<_Sequence>());
}
-#endif
-
- /* Fallback overload for which we can't say, assume it is valid. */
- template<typename _Iterator, typename _Sequence, typename _InputIterator>
- inline bool
- __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>&,
- _InputIterator,
- std::input_iterator_tag)
- { return true; }
-
- template<typename _Iterator, typename _Sequence,
- typename _Integral>
+
+ /* Handle the case where we aren't really inserting a range after all */
+ template<typename _Iterator, typename _Sequence, typename _Integral>
inline bool
- __foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>& __it,
- _Integral __other,
+ __foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>&,
+ _Integral, _Integral,
std::__true_type)
{ return true; }
+ /* Handle all iterators. */
template<typename _Iterator, typename _Sequence,
typename _InputIterator>
inline bool
__foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>& __it,
- _InputIterator __other,
+ _InputIterator __other, _InputIterator __other_end,
std::__false_type)
{
- return (_Insert_range_from_self_is_safe<_Sequence>::__value
- || __foreign_iterator_aux2(__it, __other,
- std::__iterator_category(__it)));
+ return _Insert_range_from_self_is_safe<_Sequence>::__value
+ || __foreign_iterator_aux2(__it, __other, __other_end);
}
template<typename _Iterator, typename _Sequence,
typename _InputIterator>
inline bool
__foreign_iterator(const _Safe_iterator<_Iterator, _Sequence>& __it,
- _InputIterator __other)
+ _InputIterator __other, _InputIterator __other_end)
{
typedef typename std::__is_integer<_InputIterator>::__type _Integral;
- return __foreign_iterator_aux(__it, __other, _Integral());
+ return __foreign_iterator_aux(__it, __other, __other_end, _Integral());
}
/** Checks that __s is non-NULL or __n == 0, and then returns __s. */
@@ -99,14 +99,15 @@ _GLIBCXX_DEBUG_VERIFY(!_Position._M_is_end(), \
* into a container at a specific position requires that the iterator
* be nonsingular (i.e., either dereferenceable or past-the-end),
* that it reference the sequence we are inserting into, and that the
- * iterator range [_First, Last) is a valid (possibly empty)
- * range. Note that this macro is only valid when the container is a
+ * iterator range [_First, _Last) is a valid (possibly empty)
+ * range which does not reference the sequence we are inserting into.
+ * Note that this macro is only valid when the container is a
* _Safe_sequence and the _Position iterator is a _Safe_iterator.
*/
#define __glibcxx_check_insert_range(_Position,_First,_Last) \
__glibcxx_check_valid_range(_First,_Last); \
__glibcxx_check_insert(_Position); \
-_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First),\
+_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\
_M_message(__gnu_debug::__msg_insert_range_from_self)\
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last) \
@@ -117,18 +118,15 @@ _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First),\
* into a container after a specific position requires that the iterator
* be nonsingular (i.e., either dereferenceable or past-the-end),
* that it reference the sequence we are inserting into, and that the
- * iterator range [_First, Last) is a valid (possibly empty)
- * range. Note that this macro is only valid when the container is a
- * _Safe_sequence and the iterator is a _Safe_iterator.
- *
- * @todo We would like to be able to check for noninterference of
- * _Position and the range [_First, _Last), but that can't (in
- * general) be done.
+ * iterator range [_First, _Last) is a valid (possibly empty)
+ * range which does not reference the sequence we are inserting into.
+ * Note that this macro is only valid when the container is a
+ * _Safe_sequence and the _Position iterator is a _Safe_iterator.
*/
#define __glibcxx_check_insert_range_after(_Position,_First,_Last) \
__glibcxx_check_valid_range(_First,_Last); \
-__glibcxx_check_insert_after(_Position); \
-_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First),\
+__glibcxx_check_insert_after(_Position); \
+_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\
_M_message(__gnu_debug::__msg_insert_range_from_self)\
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last) \
@@ -343,7 +341,7 @@ _GLIBCXX_DEBUG_VERIFY(this != &_Other, \
_M_message(__gnu_debug::__msg_self_move_assign) \
._M_sequence(*this, "this"))
-// Verify that load factor is position
+// Verify that load factor is positive
#define __glibcxx_check_max_load_factor(_F) \
_GLIBCXX_DEBUG_VERIFY(_F > 0.0f, \
_M_message(__gnu_debug::__msg_valid_load_factor) \
@@ -718,4 +718,17 @@ namespace __debug
} // namespace std
+namespace __gnu_debug
+{
+ template<typename _Tp, typename _Alloc>
+ struct _Is_contiguous_sequence<std::__debug::vector<_Tp, _Alloc> >
+ : std::__true_type
+ { };
+
+ template<typename _Alloc>
+ struct _Is_contiguous_sequence<std::__debug::vector<bool, _Alloc> >
+ : std::__false_type
+ { };
+}
+
#endif
@@ -15,12 +15,10 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
//
-// { dg-options "-std=gnu++11" }
// { dg-require-debug-mode "" }
// { dg-do run { xfail *-*-* } }
#include <vector>
-#include <debug/checks.h>
void test01()
{
new file mode 100644
@@ -0,0 +1,35 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-require-debug-mode "" }
+
+// PR libstdc++/60587
+
+#include <vector>
+
+int main() {
+ std::vector<int> a, b;
+ a.push_back(1);
+ a.insert(a.end(), b.begin(), b.end());
+ b.push_back(1L);
+ a.insert(a.end(), b.begin(), b.end());
+
+ std::vector<long> c;
+ a.insert(a.end(), c.begin(), c.end());
+ c.push_back(1L);
+ a.insert(a.end(), c.begin(), c.end());
+}
new file mode 100644
@@ -0,0 +1,29 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-require-debug-mode "" }
+// { dg-do run { xfail *-*-* } }
+
+// PR libstdc++/60587
+
+#include <vector>
+
+int main() {
+ std::vector<int> a;
+ a.push_back(1);
+ a.insert(a.end(), a.begin(), a.begin()); // Expected to abort here
+}