This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fwd: Debug algos evolution


Hi

I had no feedback regarding this proposal which I am submiting again. I have completed it to be able to completely remove debug.h from bits/stl_algobase.h.

    Do you think it has any interest for libstdc++ ?

François


-------- Original Message --------
Subject: 	Debug algos evolution
Date: 	Thu, 14 Nov 2013 22:03:28 +0100
From: 	François Dumont <frs.dumont@gmail.com>
To: 	libstdc++@gcc.gnu.org <libstdc++@gcc.gnu.org>



Hi

     Here is a proposal for an evolution of debug algos. It is far from
being complete but I would like to know first if you find it interesting.

     The new approach is to expose real debug algos rather than to have
debug macros in normal algos. To do so I had to introduce a dedicated
namespace __cxx1998_a different of the one used for debug containers
otherwise, because of ADL, the compiler do not know what version of the
algo to use when it is called with an iterator of a debug container.

     The advantage of this approach is that:
- we can implement any debug checks without polluting normal algos
- debug algos are now aware about debug iterators and can remove debug
layer before invoking normal algos. This will reduce perfomance hint of
debug mode. For instance this code:

std::vector<int> v1, v2;
//....
std::copy(v1.begin(), v1.end(), v2.begin());

will continue to rely on memmove with or without debug mode.

     Note that I have also started implementing new checks to try and
detect overlapping when invoking swap_ranges or copy or move. Paolo, you
said that we needed to use std::less to do some comparison, is it also
true for a random access iterator ?

     Some checks are even on only potential issues like in std::equal.
For the moment debug mode will detect an issue in this algo only if all
compared values are equals until we reach a past-the-end iterator. With
this evolution we will notify an issue even if the first values are not
equal. IMO it simply means that the code is wrong and will crash one day
sooner or later.

What do you think about it ?

François






Index: src/c++11/debug.cc
===================================================================
--- src/c++11/debug.cc	(revision 205497)
+++ src/c++11/debug.cc	(working copy)
@@ -182,7 +182,14 @@
     " container only holds %3; buckets",
     "load factor shall be positive",
     "allocators must be equal",
-    "attempt to insert with an iterator range [%1.name;, %2.name;) from this container"
+    "attempt to insert with an iterator range [%1.name;, %2.name;) from this"
+    " container",
+    "completing the operation might result in accessing unaccessible memory",
+    "range starting at %3.name; overlap [%1.name;, %2.name;)",
+    "copying [%1.name;, %2.name;) to [%3.name;, %3.name; + (%2.name; -"
+    " %1.name;)) won't have the expected result, ranges overlap",
+    "copying (%1.name;, %2.name;] to (%3.name; - (%2.name; - %1.name;),"
+    " %3.name;] won't have the expected result, ranges overlap"
   };
 
   void
Index: include/Makefile.am
===================================================================
--- include/Makefile.am	(revision 205497)
+++ include/Makefile.am	(working copy)
@@ -719,6 +719,10 @@
 debug_srcdir = ${glibcxx_srcdir}/include/debug
 debug_builddir = ./debug
 debug_headers = \
+	${debug_srcdir}/algo.h \
+	${debug_srcdir}/algobase.h \
+	${debug_srcdir}/algorithm \
+	${debug_srcdir}/algorithmfwd.h \
 	${debug_srcdir}/array \
 	${debug_srcdir}/bitset \
 	${debug_srcdir}/debug.h \
@@ -732,6 +736,7 @@
 	${debug_srcdir}/map.h \
 	${debug_srcdir}/multimap.h \
 	${debug_srcdir}/multiset.h \
+	${debug_srcdir}/numeric \
 	${debug_srcdir}/safe_base.h \
 	${debug_srcdir}/safe_iterator.h \
 	${debug_srcdir}/safe_iterator.tcc \
Index: include/Makefile.in
===================================================================
--- include/Makefile.in	(revision 205497)
+++ include/Makefile.in	(working copy)
@@ -980,6 +980,10 @@
 debug_srcdir = ${glibcxx_srcdir}/include/debug
 debug_builddir = ./debug
 debug_headers = \
+	${debug_srcdir}/algo.h \
+	${debug_srcdir}/algobase.h \
+	${debug_srcdir}/algorithm \
+	${debug_srcdir}/algorithmfwd.h \
 	${debug_srcdir}/array \
 	${debug_srcdir}/bitset \
 	${debug_srcdir}/debug.h \
@@ -993,6 +997,7 @@
 	${debug_srcdir}/map.h \
 	${debug_srcdir}/multimap.h \
 	${debug_srcdir}/multiset.h \
+	${debug_srcdir}/numeric \
 	${debug_srcdir}/safe_base.h \
 	${debug_srcdir}/safe_iterator.h \
 	${debug_srcdir}/safe_iterator.tcc \
Index: include/debug/safe_local_iterator.h
===================================================================
--- include/debug/safe_local_iterator.h	(revision 205497)
+++ include/debug/safe_local_iterator.h	(working copy)
@@ -321,14 +321,11 @@
     operator!=(const _Safe_local_iterator<_IteratorL, _Sequence>& __lhs,
 	       const _Safe_local_iterator<_IteratorR, _Sequence>& __rhs)
     {
-      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
+      _GLIBCXX_DEBUG_VERIFY((!__lhs._M_singular() || __lhs.base() == _IteratorL()) &&
+			    (!__rhs._M_singular() || __rhs.base() == _IteratorR()),
 			    _M_message(__msg_iter_compare_bad)
 			    ._M_iterator(__lhs, "lhs")
 			    ._M_iterator(__rhs, "rhs"));
-      _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
-			    _M_message(__msg_compare_different)
-			    ._M_iterator(__lhs, "lhs")
-			    ._M_iterator(__rhs, "rhs"));
       _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs),
 			    _M_message(__msg_local_iter_compare_bad)
 			    ._M_iterator(__lhs, "lhs")
Index: include/debug/formatter.h
===================================================================
--- include/debug/formatter.h	(revision 205497)
+++ include/debug/formatter.h	(working copy)
@@ -116,7 +116,12 @@
     __msg_valid_load_factor,
     // others
     __msg_equal_allocs,
-    __msg_insert_range_from_self
+    __msg_insert_range_from_self,
+    // algos checks
+    __msg_forbidden_mem,
+    __msg_ranges_overlap,
+    __msg_copy_bad,
+    __msg_copy_backward_bad
   };
 
   class _Error_formatter
Index: include/debug/functions.h
===================================================================
--- include/debug/functions.h	(revision 205497)
+++ include/debug/functions.h	(working copy)
@@ -175,6 +175,34 @@
       return __first;
     }
 
+  /* Arbitrary pointer type, assume they can compare */
+  inline bool
+  __can_compare_aux(const void*, const void*)
+  { return true; }
+
+  /* Try to find out if iterators can be compared each other. */
+  template<typename _InputIterator>
+    inline bool
+    __can_compare(const _InputIterator& __first, const _InputIterator& __last)
+    { return __can_compare_aux(&__first, &__last); }
+
+  /** Check if iterators are pointing to the same bucket when using unordered
+   * containers local iterators.
+   * Assume it is correct for arbitrary iterators because we can't say
+   * otherwise.
+   **/
+  template<typename _InputIterator>
+    inline bool
+    __same_bucket(const _InputIterator&, const _InputIterator&)
+    { return true; }
+
+  /* Safe local iterators know their bucket. */
+  template<typename _Iterator, typename _Sequence>
+    inline bool
+    __same_bucket(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
+		  const _Safe_local_iterator<_Iterator, _Sequence>& __last)
+    { return __first._M_in_same_bucket(__last); }
+
 #if __cplusplus >= 201103L
   // Default implementation.
   template<typename _Iterator, typename _Sequence>
@@ -294,6 +322,119 @@
       return __foreign_iterator_aux(__it, __other, _Integral());
     }
 
+  /* Gets the underlying unsafe iterator if any */
+  template<typename _Iterator>
+    inline _Iterator
+    __unsafe(_Iterator __it)
+    { return __it; }
+
+  template<typename _Iterator, typename _Sequence>
+    inline _Iterator
+    __unsafe(const _Safe_iterator<_Iterator, _Sequence>&  __it)
+    { return __it.base(); }
+
+  template<typename _Iterator, typename _Sequence>
+    inline _Iterator
+    __unsafe(const _Safe_local_iterator<_Iterator, _Sequence>&  __it)
+    { return __it.base(); }
+
+  /* Fallback assume that ranges doesn't overlap. */
+  template<typename _IIte1, typename _IIte2>
+    inline bool
+    __overlap(_IIte1, _IIte1, _IIte2)
+    { return false; }
+
+  template<typename _Ite>
+    inline bool
+    __overlap_aux(const _Ite&, const _Ite&, const _Ite&,
+		  std::input_iterator_tag)
+    { return false; }
+
+  template<typename _Ite>
+    inline bool
+    __overlap_aux(const _Ite& __first1, const _Ite& __last1,
+		  const _Ite& __first2,
+		  std::random_access_iterator_tag)
+    {
+      return __first2 < __last1
+	&& (__first2 + (__last1 - __first1) >= __first1);
+    }
+
+  /* Overload when all iterators are of the same type. */
+  template<typename _Ite>
+    inline bool
+    __overlap(const _Ite& __first1, const _Ite& __last1,
+	      const _Ite& __first2)
+    {
+      return __overlap_aux(__unsafe(__first1), __unsafe(__last1),
+			   __unsafe(__first2),
+			   std::__iterator_category(__first1));
+    }
+
+  /* Check that it is safe to copy [first, last) to result. */
+  // Fallback overload, assume it is safe.
+  template<typename _IIte, typename _OIte>
+    inline bool
+    __check_copy(_IIte, _IIte, _OIte)
+    { return true; }
+
+  // Check is done only if all iterators are of the same type and are random
+  // ones.
+  template<typename _Ite>
+    inline bool
+    __check_copy_aux(_Ite __first, _Ite __last, _Ite __result,
+		     std::random_access_iterator_tag)
+    { return __result < __first || __last <= __result; }
+
+  // Can't say.
+  template<typename _Ite>
+    inline bool
+    __check_copy_aux(_Ite, _Ite, _Ite,
+		     std::input_iterator_tag)
+    { return true; }
+
+  // Overload when all iterators are of the same type.
+  template<typename _Ite>
+    inline bool
+    __check_copy(_Ite __first, _Ite __last, _Ite __result)
+    {
+      return __check_copy_aux(__unsafe(__first), __unsafe(__last),
+			      __unsafe(__result),
+			      std::__iterator_category(__first));
+    }
+
+  /* Check that it is safe to copy (first, last] to result backward. */
+  // Fallback overload, assume it is safe.
+  template<typename _IIte, typename _OIte>
+    inline bool
+    __check_copy_backward(_IIte, _IIte, _OIte)
+    { return true; }
+
+  // Check is done only if all iterators are of the same type and are random
+  // ones.
+  template<typename _Ite>
+    inline bool
+    __check_copy_backward_aux(_Ite __first, _Ite __last, _Ite __result,
+			      std::random_access_iterator_tag)
+    { return __result <= __first || __last < __result; }
+
+  // Can't say.
+  template<typename _Ite>
+    inline bool
+    __check_copy_backward_aux(_Ite, _Ite, _Ite,
+			      std::input_iterator_tag)
+    { return true; }
+
+  // Overload when all iterators are of the same type.
+  template<typename _Ite>
+    inline bool
+    __check_copy_backward(_Ite __first, _Ite __last, _Ite __result)
+    {
+      return __check_copy_backward_aux(__unsafe(__first), __unsafe(__last),
+				       __unsafe(__result),
+				       std::__iterator_category(__first));
+    }
+
   /** Checks that __s is non-NULL or __n == 0, and then returns __s. */
   template<typename _CharT, typename _Integer>
     inline const _CharT*
@@ -557,6 +698,29 @@
     inline typename _Siter_base<_Iterator>::iterator_type
     __base(_Iterator __it)
     { return _Siter_base<_Iterator>::_S_base(__it); }
+
+  template<typename _Iterator>
+    inline _Iterator
+    __safe(_Iterator, _Iterator __it)
+    { return __it; }
+
+  template<typename _Iterator, typename _Sequence>
+    inline _Safe_iterator<_Iterator, _Sequence>
+    __safe(const _Safe_iterator<_Iterator, _Sequence>& __safe_it,
+	   _Iterator __it)
+    {
+      return _Safe_iterator<_Iterator, _Sequence>(__it,
+						  __safe_it._M_get_sequence());
+    }
+
+  template<typename _Iterator, typename _Sequence>
+    inline _Safe_local_iterator<_Iterator, _Sequence>
+    __safe(const _Safe_local_iterator<_Iterator, _Sequence>& __safe_it,
+	   _Iterator __it)
+    {
+      return _Safe_local_iterator<_Iterator, _Sequence>(__it,
+						__safe_it._M_get_sequence());
+    }
 } // namespace __gnu_debug
 
 #endif
Index: include/debug/safe_iterator.tcc
===================================================================
--- include/debug/safe_iterator.tcc	(revision 205497)
+++ include/debug/safe_iterator.tcc	(working copy)
@@ -43,7 +43,7 @@
       if (__n < 0)
 	{
 	  std::pair<difference_type, _Distance_precision> __dist =
-	    __get_distance(_M_get_sequence()->_M_base().begin(), base());
+	    __get_distance_from_begin(*this);
 	  bool __ok =  ((__dist.second == __dp_exact && __dist.first >= -__n)
 			|| (__dist.second != __dp_exact && __dist.first > 0));
 	  return __ok;
@@ -51,7 +51,7 @@
       else
 	{
 	  std::pair<difference_type, _Distance_precision> __dist =
-	    __get_distance(base(), _M_get_sequence()->_M_base().end());
+	    __get_distance_to_end(*this);
 	  bool __ok = ((__dist.second == __dp_exact && __dist.first >= __n)
 		       || (__dist.second != __dp_exact && __dist.first > 0));
 	  return __ok;
@@ -69,7 +69,7 @@
       /* Determine if we can order the iterators without the help of
 	 the container */
       std::pair<difference_type, _Distance_precision> __dist =
-	__get_distance(base(), __rhs.base());
+	__get_distance(*this, __rhs);
       switch (__dist.second) {
       case __dp_equality:
 	if (__dist.first == 0)
@@ -81,20 +81,53 @@
 	return __dist.first >= 0;
       }
 
-      /* We can only test for equality, but check if one of the
-	 iterators is at an extreme. */
-      /* Optim for classic [begin, it) or [it, end) ranges, limit checks
-       * when code is valid.  Note, for the special case of forward_list,
-       * before_begin replaces the role of begin.  */ 
-      if (_M_is_beginnest() || __rhs._M_is_end())
-	return true;
-      if (_M_is_end() || __rhs._M_is_beginnest())
-	return false;
-
       // Assume that this is a valid range; we can't check anything else
       return true;
     }
+
+  template<typename _Iterator, typename _Sequence>
+    std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+	      _Distance_precision>
+    __get_distance_aux(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
+		       const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+    {
+      typedef std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+			_Distance_precision> _Pair;
+      if (__lhs.base() == __rhs.base())
+	return _Pair(0, __dp_exact);
+	
+      if (__lhs._M_is_beginnest())
+	if (__rhs._M_is_end())
+	  // For forward_list we could return size() + 1 but forward_list has
+	  // no size() so we do not have to care about being more accurate.
+	  return _Size_helper<_Sequence>::_S_size(__lhs);
+        else if (__rhs._M_is_begin())
+	  return _Pair(1, __dp_exact);
+        else
+	  return _Pair(1, __dp_sign);
+      else if (__lhs._M_is_begin())
+	if (__rhs._M_is_beginnest())
+	  return _Pair(-1, __dp_exact);
+        else if (__rhs._M_is_end())
+	  return _Size_helper<_Sequence>::_S_size(__lhs);
+        else
+	  return _Pair(1, __dp_sign);
+      else if (__lhs._M_is_end())
+	if (__rhs._M_is_beginnest() || __rhs._M_is_begin())
+	  {
+	    _Pair __cont_size =
+	      _Size_helper<_Sequence>::_S_size(__lhs);
+	    return _Pair(-__cont_size.first, __cont_size.second);
+	  }
+        else
+	  return _Pair(-1, __dp_sign);
+      else if (__rhs._M_is_beginnest() || __rhs._M_is_begin())
+	return _Pair(-1, __dp_sign);
+      else if (__rhs._M_is_end())
+	return _Pair(1, __dp_sign);
+      else
+	return _Pair(1, __dp_equality);
+    }
 } // namespace __gnu_debug
 
 #endif
-
Index: include/debug/forward_list
===================================================================
--- include/debug/forward_list	(revision 205497)
+++ include/debug/forward_list	(working copy)
@@ -806,6 +806,24 @@
       std::__debug::forward_list<_Tp, _Alloc> >
     { enum { __value = 1 }; };
 #endif
+
+  template<class _Tp, class _Alloc>
+    struct _Size_helper<std::__debug::forward_list<_Tp, _Alloc> >
+    {
+      typedef std::__debug::forward_list<_Tp, _Alloc> _Sequence;
+
+      template<typename _Iterator>
+	static std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+			 _Distance_precision>
+	_S_size(const _Safe_iterator<_Iterator, _Sequence>& __it)
+	{
+	  typedef typename _Diff_type_helper<_Iterator>::_Type _DiffType;
+	  if (__it._M_get_sequence()->empty())
+	    return std::make_pair(_DiffType(0), __dp_exact);
+	  else
+	    return std::make_pair(_DiffType(1), __dp_sign);
+	}
+    };
 }
 
 #endif
Index: include/debug/safe_local_iterator.tcc
===================================================================
--- include/debug/safe_local_iterator.tcc	(revision 205497)
+++ include/debug/safe_local_iterator.tcc	(working copy)
@@ -32,6 +32,29 @@
 namespace __gnu_debug
 {
   template<typename _Iterator, typename _Sequence>
+    std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+	      _Distance_precision>
+    __get_distance_aux(const _Safe_local_iterator<_Iterator, _Sequence>& __lhs,
+		       const _Safe_local_iterator<_Iterator, _Sequence>& __rhs)
+    {
+      typedef std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+			_Distance_precision> _Pair;
+      if (__lhs.base() == __rhs.base())
+	return _Pair(0, __dp_exact);
+	
+      if (__lhs._M_is_begin())
+	return _Pair(1, __dp_sign);
+      else if (__lhs._M_is_end())
+	return _Pair(-1, __dp_sign);
+      else if (__rhs._M_is_begin())
+	return _Pair(-1, __dp_sign);
+      else if (__rhs._M_is_end())
+	return _Pair(1, __dp_sign);
+      else
+	return _Pair(1, __dp_equality);
+    }
+
+  template<typename _Iterator, typename _Sequence>
     bool
     _Safe_local_iterator<_Iterator, _Sequence>::
     _M_valid_range(const _Safe_local_iterator& __rhs) const
@@ -44,7 +67,7 @@
       /* Determine if we can order the iterators without the help of
 	 the container */
       std::pair<difference_type, _Distance_precision> __dist =
-	__get_distance(base(), __rhs.base());
+	__get_distance(*this, __rhs);
       switch (__dist.second)
 	{
 	case __dp_equality:
@@ -57,18 +80,10 @@
 	  return __dist.first >= 0;
 	}
 
-      /* We can only test for equality, but check if one of the
-	 iterators is at an extreme. */
-      /* Optim for classic [begin, it) or [it, end) ranges, limit checks
-       * when code is valid. */
-      if (_M_is_begin() || __rhs._M_is_end())
-	return true;
-      if (_M_is_end() || __rhs._M_is_begin())
-	return false;
-
       // Assume that this is a valid range; we can't check anything else
       return true;
     }
+
 } // namespace __gnu_debug
 
 #endif
Index: include/debug/macros.h
===================================================================
--- include/debug/macros.h	(revision 205497)
+++ include/debug/macros.h	(working copy)
@@ -49,6 +49,29 @@
 #define _GLIBCXX_DEBUG_VERIFY(_Condition,_ErrorMessage)			\
   _GLIBCXX_DEBUG_VERIFY_AT(_Condition,_ErrorMessage,__FILE__,__LINE__)
 
+// Verify that [_First, _Last) can be a range
+#define __glibcxx_check_can_compare(_First, _Last)			\
+  _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__can_compare(_First, _Last),	\
+			_M_message(__gnu_debug::__msg_valid_range)	\
+			._M_iterator(_First, #_First)			\
+			._M_iterator(_Last, #_Last));			\
+  _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__same_bucket(_First, _Last),	\
+		_M_message(__gnu_debug::__msg_local_iter_compare_bad)	\
+			._M_iterator(_First, #_First)			\
+			._M_iterator(_Last, #_Last))
+
+/** Verify that [First, _Last) forms a valid range given its computed distance
+ * information.
+ */
+#define __glibcxx_check_range_from_dist(_First, _Last, _Dist)	\
+  _GLIBCXX_DEBUG_VERIFY((_Dist.second == __gnu_debug::__dp_equality ||	\
+			 _Dist.first >= 0) &&				\
+			(_Dist.first == 0 ||				\
+			 __gnu_debug::__check_dereferenceable(_First)),	\
+			_M_message(__gnu_debug::__msg_valid_range)	\
+			._M_iterator(_First, #_First)			\
+			._M_iterator(_Last, #_Last))
+
 // Verify that [_First, _Last) forms a valid iterator range.
 #define __glibcxx_check_valid_range(_First,_Last)			\
 _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last),	\
@@ -63,6 +86,33 @@
 		      ._M_iterator(_First, #_First)			\
 		      ._M_iterator(_Last, #_Last))
 
+/** Verify that range [_Pos, _Pos + (_Last - _First)) doesn't overlap range
+ *  [_First, _Last).
+ */
+#define __glibcxx_check_overlap(_First,_Last,_Pos)			\
+  _GLIBCXX_DEBUG_VERIFY(!__gnu_debug::__overlap(_First, _Last, _Pos),	\
+			_M_message(__gnu_debug::__msg_ranges_overlap)	\
+			._M_iterator(_First, #_First)			\
+			._M_iterator(_Last, #_Last)			\
+			._M_iterator(_Pos, #_Pos))
+
+/** Verify that it is safe to copy [_First, _Last) to _Result */
+#define __glibcxx_check_copy(_First,_Last,_Result)			\
+  _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_copy(_First, _Last, _Result),\
+			_M_message(__gnu_debug::__msg_copy_bad)		\
+			._M_iterator(_First, #_First)			\
+			._M_iterator(_Last, #_Last)			\
+			._M_iterator(_Result, #_Result))
+
+/** Verify that it is safe to copy (_First, _Last] to _Result backward */
+#define __glibcxx_check_copy_backward(_First,_Last,_Result)		\
+  _GLIBCXX_DEBUG_VERIFY(						\
+	__gnu_debug::__check_copy_backward(_First, _Last, _Result),	\
+			_M_message(__gnu_debug::__msg_copy_backward_bad)\
+			._M_iterator(_First, #_First)			\
+			._M_iterator(_Last, #_Last)			\
+			._M_iterator(_Result, #_Result))
+
 /** Verify that we can insert into *this with the iterator _Position.
  *  Insertion into a container at a specific position requires that
  *  the iterator be nonsingular, either dereferenceable or past-the-end,
Index: include/debug/list
===================================================================
--- include/debug/list	(revision 205497)
+++ include/debug/list	(working copy)
@@ -797,6 +797,24 @@
   template<class _Tp, class _Alloc>
     struct _Insert_range_from_self_is_safe<std::__debug::list<_Tp, _Alloc> >
     { enum { __value = 1 }; };
+
+  template<class _Tp, class _Alloc>
+    struct _Size_helper<std::__debug::list<_Tp, _Alloc> >
+    {
+      typedef std::__debug::list<_Tp, _Alloc> _Sequence;
+
+      template<typename _Iterator>
+	static std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+			 _Distance_precision>
+	_S_size(const _Safe_iterator<_Iterator, _Sequence>& __it)
+	{
+	  typedef typename _Diff_type_helper<_Iterator>::_Type _DiffType;
+	  if (__it._M_get_sequence()->empty())
+	    return std::make_pair(_DiffType(0), __dp_exact);
+	  else
+	    return std::make_pair(_DiffType(1), __dp_sign);
+	}
+    };
 }
 #endif
 
Index: include/debug/safe_iterator.h
===================================================================
--- include/debug/safe_iterator.h	(revision 205497)
+++ include/debug/safe_iterator.h	(working copy)
@@ -35,13 +35,14 @@
 #include <debug/safe_base.h>
 #include <bits/stl_pair.h>
 #include <ext/type_traits.h>
+#include <ext/numeric_traits.h>
 
 namespace __gnu_debug
 {
   /** Helper struct to deal with sequence offering a before_begin
    *  iterator.
    **/
-  template <typename _Sequence>
+  template<typename _Sequence>
     struct _BeforeBeginHelper
     {
       template<typename _Iterator>
@@ -62,6 +63,17 @@
   __check_singular_aux(const _Safe_iterator_base* __x)
   { return __x->_M_singular(); }
 
+  /** Iterators that derives from _Safe_iterator_base know if they are
+   *  comparable or not.
+   **/
+  inline bool
+  __can_compare_aux(const _Safe_iterator_base* __first,
+		    const _Safe_iterator_base* __last)
+  { return __first->_M_can_compare(*__last); }
+
+  template<typename _Iterator, typename _Sequence>
+    class _Safe_iterator;
+
   /** The precision to which we can calculate the distance between
    *  two iterators.
    */
@@ -72,31 +84,131 @@
       __dp_exact     //< Can determine distance precisely
     };
 
+  /** Helper struct to get a non-void difference type; workaround for output
+   * iterators that might have a void one.
+   */
+  template<typename _Iterator,
+	   typename _DiffType
+	     = typename std::iterator_traits<_Iterator>::difference_type>
+    struct _Diff_type_helper
+    { typedef _DiffType _Type; };
+
+  template<typename _Iterator>
+    struct _Diff_type_helper<_Iterator, void>
+    { typedef std::ptrdiff_t _Type; };
+
+  /** Helper struct giving sequence size() if available and if O(1) **/
+  template<typename _Sequence>
+    struct _Size_helper
+    {
+      template<typename _Iterator>
+	static std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+			 _Distance_precision>
+	_S_size(const _Safe_iterator<_Iterator, _Sequence>& __it)
+	{
+	  typedef typename _Diff_type_helper<_Iterator>::_Type _DiffType;
+
+	  // Potential conversion from unsigned to signed
+	  if (__it._M_get_sequence()->size()
+	      > __gnu_cxx::__numeric_traits<_DiffType>::__max)
+	    return std::make_pair(__gnu_cxx::__numeric_traits<_DiffType>::__max,
+				  __dp_sign);
+	  return std::make_pair
+	    (static_cast<_DiffType>(__it._M_get_sequence()->size()), __dp_exact);
+	}
+    };
+
   /** Determine the distance between two iterators with some known
-   *	precision.
+   * precision.
   */
   template<typename _Iterator>
-    inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
+    inline std::pair<typename _Diff_type_helper<_Iterator>::_Type,
 		     _Distance_precision>
+    __get_distance_aux(const _Iterator& __lhs, const _Iterator& __rhs)
+    {
+      typedef std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+			_Distance_precision> _Pair;
+	if (__lhs == __rhs)
+	  return _Pair(0, __dp_exact);
+
+	return _Pair(1, __dp_equality);
+    }
+
+  template<typename _Iterator, typename _Sequence>
+    std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+	      _Distance_precision>
+    __get_distance_aux(const _Safe_iterator<_Iterator, _Sequence>&,
+		       const _Safe_iterator<_Iterator, _Sequence>&);
+
+  template<typename _Iterator, typename _Sequence>
+    std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+	      _Distance_precision>
+    __get_distance_aux(const _Safe_local_iterator<_Iterator, _Sequence>&,
+		       const _Safe_local_iterator<_Iterator, _Sequence>&);
+
+  template<typename _Iterator>
+    inline std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+		     _Distance_precision>
     __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
 		   std::random_access_iterator_tag)
     { return std::make_pair(__rhs - __lhs, __dp_exact); }
 
   template<typename _Iterator>
-    inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
+    inline std::pair<typename _Diff_type_helper<_Iterator>::_Type,
 		     _Distance_precision>
     __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
-		   std::forward_iterator_tag)
-    { return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); }
+		   std::input_iterator_tag)
+    { return __get_distance_aux(__lhs, __rhs); }
 
   template<typename _Iterator>
-    inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
+    inline std::pair<typename _Diff_type_helper<_Iterator>::_Type,
 		     _Distance_precision>
     __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
+    { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
+
+  // Get distance from beginning of iterator sequence if we are able to access
+  // it.
+  template<typename _Iterator>
+    inline std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+		     _Distance_precision>
+    __get_distance_from_begin(const _Iterator&)
+    { return std::make_pair(0, __dp_equality); }
+
+  template<typename _Iterator, typename _Sequence>
+    inline std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+		     _Distance_precision>
+    __get_distance_from_begin(const _Safe_iterator<_Iterator, _Sequence>& __to)
+     {
+      if (__to._M_is_beginnest() || __to._M_is_begin())
+	return std::make_pair(0, __dp_exact);
+
+      if (__to._M_is_end())
+	return _Size_helper<_Sequence>::_S_size(__to);
+
+      return __get_distance(__to._M_get_sequence()->_M_base().begin(),
+			    __to.base());
+     }
+ 
+  // Get distance to the end of iterator's sequence if we are able to access it.
+  template<typename _Iterator>
+    inline std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+		     _Distance_precision>
+    __get_distance_to_end(const _Iterator&)
+    { return std::make_pair(0, __dp_equality); }
+
+  template<typename _Iterator, typename _Sequence>
+    inline std::pair<typename _Diff_type_helper<_Iterator>::_Type,
+		     _Distance_precision>
+    __get_distance_to_end(const _Safe_iterator<_Iterator, _Sequence>& __from)
     {
-      typedef typename std::iterator_traits<_Iterator>::iterator_category
-	  _Category;
-      return __get_distance(__lhs, __rhs, _Category());
+      if (__from._M_is_beginnest() || __from._M_is_begin())
+	return _Size_helper<_Sequence>::_S_size(__from);
+
+      if (__from._M_is_end())
+	return std::make_pair(0, __dp_exact);
+
+      return __get_distance(__from.base(),
+			    __from._M_get_sequence()->_M_base().end());
     }
 
   /** \brief Safe iterator wrapper.
@@ -445,7 +557,10 @@
       bool
       _M_valid_range(const _Safe_iterator& __rhs) const;
 
-      // The sequence this iterator references.
+      // The sequence this iterator references. Need a pointer to const when
+      // const_iterator so that accessing another iterator from it gives a
+      // result consistent with *this iterator, a const_iterator if called from
+      // a const_iterator and an iterator from an iterator.
       typename
       __gnu_cxx::__conditional_type<std::__are_same<_Const_iterator,
 						    _Safe_iterator>::__value,
@@ -500,7 +615,8 @@
                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
-      _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
+      _GLIBCXX_DEBUG_VERIFY((! __lhs._M_singular() || __lhs.base() == _Iterator()) &&
+			    (! __rhs._M_singular() || __rhs.base() == _Iterator()),
 			    _M_message(__msg_iter_compare_bad)
 			    ._M_iterator(__lhs, "lhs")
 			    ._M_iterator(__rhs, "rhs"));
Index: include/std/algorithm
===================================================================
--- include/std/algorithm	(revision 205497)
+++ include/std/algorithm	(working copy)
@@ -61,6 +61,10 @@
 #include <bits/stl_algobase.h>
 #include <bits/stl_algo.h>
 
+#ifdef _GLIBCXX_DEBUG
+# include <debug/algorithm>
+#endif
+
 #ifdef _GLIBCXX_PARALLEL
 # include <parallel/algorithm>
 #endif
Index: include/std/numeric
===================================================================
--- include/std/numeric	(revision 205497)
+++ include/std/numeric	(working copy)
@@ -61,6 +61,10 @@
 #include <bits/stl_iterator_base_types.h>
 #include <bits/stl_numeric.h>
 
+#ifdef _GLIBCXX_DEBUG
+# include <debug/numeric>
+#endif
+
 #ifdef _GLIBCXX_PARALLEL
 # include <parallel/numeric>
 #endif
Index: include/parallel/algorithmfwd.h
===================================================================
--- include/parallel/algorithmfwd.h	(revision 205497)
+++ include/parallel/algorithmfwd.h	(working copy)
@@ -121,6 +121,40 @@
 
   // algobase.h
   template<typename _IIter1, typename _IIter2>
+    _IIter2
+    swap_ranges(_IIter1, _IIter1, _IIter2);
+
+  template<typename _II, typename _OI>
+    _OI
+    copy(_II, _II, _OI);
+
+  template<typename _BI1, typename _BI2>
+    _BI2
+    copy_backward(_BI1, _BI1, _BI2)
+
+#if __cplusplus >= 201103L
+  template<typename _II, typename _OI>
+    _OI
+    move(_II, _II, _OI);
+
+  template<typename _BI1, typename _BI2>
+    _BI2
+    move_backward(_BI1, _BI1, _BI2)
+#endif
+
+  template<typename _FI, typename _Tp>
+    void
+    fill(_FI, _FI, const _Tp&);
+
+  template<typename _OI, typename _Size, typename _Tp>
+    _OI
+    fill_n(_OI, _Size, const _Tp&);
+
+  template<typename _FI, typename _Tp>
+    _FI
+    lower_bound(_FI, _FI, const _Tp&);
+
+  template<typename _IIter1, typename _IIter2>
     bool
     equal(_IIter1, _IIter1, _IIter2, __gnu_parallel::sequential_tag);
 
Index: include/parallel/algobase.h
===================================================================
--- include/parallel/algobase.h	(revision 205497)
+++ include/parallel/algobase.h	(working copy)
@@ -46,6 +46,46 @@
 {
 namespace __parallel
 {
+  // No parallel version for those algos.
+  template<typename _IIter1, typename _IIter2>
+    _IIter2
+    swap_ranges(_IIter1 __first1, _IIter1 __last1, _IIter2 __first2)
+    { return _GLIBCXX_STD_A::swap_ranges(__first1, __last1, __first2); }
+
+  template<typename _II, typename _OI>
+    inline _OI
+    copy(_II __first, _II __last, _OI __result)
+    { return _GLIBCXX_STD_A::copy(__first, __last, __result); }
+
+#if __cplusplus >= 201103L
+  template<typename _II, typename _OI>
+    inline _OI
+    move(_II __first, _II __last, _OI __result)
+    { return _GLIBCXX_STD_A::move(__first, __last, __result); }
+#endif
+
+  template<typename _BI1, typename _BI2>
+    inline _BI2
+    copy_backward(_BI1 __first, _BI1 __last, _BI2 __result)
+    { return _GLIBCXX_STD_A::copy_backward(__first, __last, __result); }
+
+#if __cplusplus >= 201103L
+  template<typename _BI1, typename _BI2>
+    inline _BI2
+    move_backward(_BI1 __first, _BI1 __last, _BI2 __result)
+    { return _GLIBCXX_STD_A::move_backward(__first, __last, __result); }
+#endif
+
+  template<typename _FI, typename _Tp>
+    inline void
+    fill(_FI __first, _FI __last, const _Tp& __value)
+    { _GLIBCXX_STD_A::fill(__first, __last, __value); }
+
+  template<typename _OI, typename _Size, typename _Tp>
+    inline _OI
+    fill_n(_OI __first, _Size __n, const _Tp& __value)
+    { return _GLIBCXX_STD_A::fill_n(__first, __n, __value); }
+
   // NB: equal and lexicographical_compare require mismatch.
 
   // Sequential fallback
@@ -198,6 +238,11 @@
     }
 #endif
 
+  template<typename _FI, typename _Tp>
+    inline _FI
+    lower_bound(_FI __first, _FI __last, const _Tp& __val)
+    { return _GLIBCXX_STD_A::lower_bound(__first, __last, __val); }
+
   // Sequential fallback
   template<typename _IIter1, typename _IIter2>
     inline bool
Index: include/bits/algorithmfwd.h
===================================================================
--- include/bits/algorithmfwd.h	(revision 205497)
+++ include/bits/algorithmfwd.h	(working copy)
@@ -208,6 +208,10 @@
     bool 
     binary_search(_FIter, _FIter, const _Tp&, _Compare);
 
+_GLIBCXX_END_NAMESPACE_VERSION
+
+_GLIBCXX_BEGIN_NAMESPACE_ALGO
+
   template<typename _IIter, typename _OIter>
     _OIter 
     copy(_IIter, _IIter, _OIter);
@@ -216,6 +220,10 @@
     _BIter2
     copy_backward(_BIter1, _BIter1, _BIter2);
 
+_GLIBCXX_END_NAMESPACE_ALGO
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
 #if __cplusplus >= 201103L
   template<typename _IIter, typename _OIter, typename _Predicate>
     _OIter
@@ -237,6 +245,10 @@
     pair<_FIter, _FIter>
     equal_range(_FIter, _FIter, const _Tp&, _Compare);
 
+_GLIBCXX_END_NAMESPACE_VERSION
+
+_GLIBCXX_BEGIN_NAMESPACE_ALGO
+
   template<typename _FIter, typename _Tp>
     void 
     fill(_FIter, _FIter, const _Tp&);
@@ -245,6 +257,10 @@
     _OIter
     fill_n(_OIter, _Size, const _Tp&);
 
+_GLIBCXX_END_NAMESPACE_ALGO
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
   // find
 
   template<typename _FIter1, typename _FIter2>
@@ -335,10 +351,18 @@
     void 
     iter_swap(_FIter1, _FIter2);
 
+_GLIBCXX_END_NAMESPACE_VERSION
+
+_GLIBCXX_BEGIN_NAMESPACE_ALGO
+
   template<typename _FIter, typename _Tp>
     _FIter 
     lower_bound(_FIter, _FIter, const _Tp&);
 
+_GLIBCXX_END_NAMESPACE_ALGO
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
   template<typename _FIter, typename _Tp, typename _Compare>
     _FIter 
     lower_bound(_FIter, _FIter, const _Tp&, _Compare);
@@ -566,10 +590,18 @@
 #endif
     ;
 
+_GLIBCXX_END_NAMESPACE_VERSION
+
+_GLIBCXX_BEGIN_NAMESPACE_ALGO
+
   template<typename _FIter1, typename _FIter2>
     _FIter2 
     swap_ranges(_FIter1, _FIter1, _FIter2);
 
+_GLIBCXX_END_NAMESPACE_ALGO
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
   // transform
 
   template<typename _FIter>
@@ -818,6 +850,10 @@
 _GLIBCXX_END_NAMESPACE_ALGO
 } // namespace std
 
+#ifdef _GLIBCXX_DEBUG
+# include <debug/algorithmfwd.h>
+#endif
+
 #ifdef _GLIBCXX_PARALLEL
 # include <parallel/algorithmfwd.h>
 #endif
Index: include/bits/stl_algobase.h
===================================================================
--- include/bits/stl_algobase.h	(revision 205497)
+++ include/bits/stl_algobase.h	(working copy)
@@ -66,7 +66,6 @@
 #include <bits/stl_iterator_base_funcs.h>
 #include <bits/stl_iterator.h>
 #include <bits/concept_check.h>
-#include <debug/debug.h>
 #include <bits/move.h> // For std::swap and _GLIBCXX_MOVE
 #include <bits/predefined_ops.h>
 
@@ -149,6 +148,10 @@
 #endif
     }
 
+_GLIBCXX_END_NAMESPACE_VERSION
+
+_GLIBCXX_BEGIN_NAMESPACE_ALGO
+
   /**
    *  @brief Swap the elements of two sequences.
    *  @ingroup mutating_algorithms
@@ -171,13 +174,16 @@
 				  _ForwardIterator1>)
       __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
 				  _ForwardIterator2>)
-      __glibcxx_requires_valid_range(__first1, __last1);
 
       for (; __first1 != __last1; ++__first1, ++__first2)
 	std::iter_swap(__first1, __first2);
       return __first2;
     }
 
+_GLIBCXX_END_NAMESPACE_ALGO
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
   /**
    *  @brief This does what you think it does.
    *  @ingroup sorting_algorithms
@@ -434,6 +440,10 @@
 					     std::__niter_base(__result)));
     }
 
+_GLIBCXX_END_NAMESPACE_VERSION
+
+_GLIBCXX_BEGIN_NAMESPACE_ALGO
+
   /**
    *  @brief Copies the range [first,last) into result.
    *  @ingroup mutating_algorithms
@@ -459,7 +469,6 @@
       __glibcxx_function_requires(_InputIteratorConcept<_II>)
       __glibcxx_function_requires(_OutputIteratorConcept<_OI,
 	    typename iterator_traits<_II>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
 
       return (std::__copy_move_a2<__is_move_iterator<_II>::__value>
 	      (std::__miter_base(__first), std::__miter_base(__last),
@@ -492,7 +501,6 @@
       __glibcxx_function_requires(_InputIteratorConcept<_II>)
       __glibcxx_function_requires(_OutputIteratorConcept<_OI,
 	    typename iterator_traits<_II>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
 
       return std::__copy_move_a2<true>(std::__miter_base(__first),
 				       std::__miter_base(__last), __result);
@@ -503,6 +511,10 @@
 #define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::copy(_Tp, _Up, _Vp)
 #endif
 
+_GLIBCXX_END_NAMESPACE_ALGO
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
   template<bool, bool, typename>
     struct __copy_move_backward
     {
@@ -607,6 +619,10 @@
 		   std::__niter_base(__result)));
     }
 
+_GLIBCXX_END_NAMESPACE_VERSION
+
+_GLIBCXX_BEGIN_NAMESPACE_ALGO
+
   /**
    *  @brief Copies the range [first,last) into result.
    *  @ingroup mutating_algorithms
@@ -635,7 +651,6 @@
       __glibcxx_function_requires(_ConvertibleConcept<
 	    typename iterator_traits<_BI1>::value_type,
 	    typename iterator_traits<_BI2>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
 
       return (std::__copy_move_backward_a2<__is_move_iterator<_BI1>::__value>
 	      (std::__miter_base(__first), std::__miter_base(__last),
@@ -671,7 +686,6 @@
       __glibcxx_function_requires(_ConvertibleConcept<
 	    typename iterator_traits<_BI1>::value_type,
 	    typename iterator_traits<_BI2>::value_type>)
-      __glibcxx_requires_valid_range(__first, __last);
 
       return std::__copy_move_backward_a2<true>(std::__miter_base(__first),
 						std::__miter_base(__last),
@@ -683,6 +697,10 @@
 #define _GLIBCXX_MOVE_BACKWARD3(_Tp, _Up, _Vp) std::copy_backward(_Tp, _Up, _Vp)
 #endif
 
+_GLIBCXX_END_NAMESPACE_ALGO
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
   template<typename _ForwardIterator, typename _Tp>
     inline typename
     __gnu_cxx::__enable_if<!__is_scalar<_Tp>::__value, void>::__type
@@ -715,6 +733,10 @@
 		       __last - __first);
     }
 
+_GLIBCXX_END_NAMESPACE_VERSION
+
+_GLIBCXX_BEGIN_NAMESPACE_ALGO
+
   /**
    *  @brief Fills the range [first,last) with copies of value.
    *  @ingroup mutating_algorithms
@@ -734,12 +756,15 @@
       // concept requirements
       __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
 				  _ForwardIterator>)
-      __glibcxx_requires_valid_range(__first, __last);
 
       std::__fill_a(std::__niter_base(__first), std::__niter_base(__last),
 		    __value);
     }
 
+_GLIBCXX_END_NAMESPACE_ALGO
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
   template<typename _OutputIterator, typename _Size, typename _Tp>
     inline typename
     __gnu_cxx::__enable_if<!__is_scalar<_Tp>::__value, _OutputIterator>::__type
@@ -772,6 +797,10 @@
       return __first + __n;
     }
 
+_GLIBCXX_END_NAMESPACE_VERSION
+
+_GLIBCXX_BEGIN_NAMESPACE_ALGO
+
   /**
    *  @brief Fills the range [first,first+n) with copies of value.
    *  @ingroup mutating_algorithms
@@ -797,6 +826,10 @@
       return _OI(std::__fill_n_a(std::__niter_base(__first), __n, __value));
     }
 
+_GLIBCXX_END_NAMESPACE_ALGO
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
   template<bool _BoolType>
     struct __equal
     {
@@ -974,6 +1007,10 @@
       return __first;
     }
 
+_GLIBCXX_END_NAMESPACE_VERSION
+
+_GLIBCXX_BEGIN_NAMESPACE_ALGO
+
   /**
    *  @brief Finds the first position in which @a val could be inserted
    *         without changing the ordering.
@@ -994,12 +1031,15 @@
       __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
       __glibcxx_function_requires(_LessThanOpConcept<
 	    typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
-      __glibcxx_requires_partitioned_lower(__first, __last, __val);
 
       return std::__lower_bound(__first, __last, __val,
 				__gnu_cxx::__ops::__iter_less_val());
     }
 
+_GLIBCXX_END_NAMESPACE_ALGO
+
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
   /// This is a helper function for the sort routines and for random.tcc.
   //  Precondition: __n > 0.
   inline _GLIBCXX_CONSTEXPR int
@@ -1052,7 +1092,6 @@
       __glibcxx_function_requires(_EqualOpConcept<
 	    typename iterator_traits<_II1>::value_type,
 	    typename iterator_traits<_II2>::value_type>)
-      __glibcxx_requires_valid_range(__first1, __last1);
 
       return std::__equal_aux(std::__niter_base(__first1),
 			      std::__niter_base(__last1),
@@ -1082,7 +1121,6 @@
       // concept requirements
       __glibcxx_function_requires(_InputIteratorConcept<_IIter1>)
       __glibcxx_function_requires(_InputIteratorConcept<_IIter2>)
-      __glibcxx_requires_valid_range(__first1, __last1);
 
       for (; __first1 != __last1; ++__first1, ++__first2)
 	if (!bool(__binary_pred(*__first1, *__first2)))
@@ -1114,8 +1152,6 @@
       __glibcxx_function_requires(_EqualOpConcept<
 	    typename iterator_traits<_II1>::value_type,
 	    typename iterator_traits<_II2>::value_type>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_valid_range(__first2, __last2);
 
       using _RATag = random_access_iterator_tag;
       using _Cat1 = typename iterator_traits<_II1>::iterator_category;
@@ -1160,8 +1196,6 @@
       // concept requirements
       __glibcxx_function_requires(_InputIteratorConcept<_IIter1>)
       __glibcxx_function_requires(_InputIteratorConcept<_IIter2>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_valid_range(__first2, __last2);
 
       using _RATag = random_access_iterator_tag;
       using _Cat1 = typename iterator_traits<_IIter1>::iterator_category;
@@ -1213,8 +1247,6 @@
       __glibcxx_function_requires(_InputIteratorConcept<_II2>)
       __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>)
       __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_valid_range(__first2, __last2);
 
       return std::__lexicographical_compare_aux(std::__niter_base(__first1),
 						std::__niter_base(__last1),
@@ -1243,8 +1275,6 @@
       // concept requirements
       __glibcxx_function_requires(_InputIteratorConcept<_II1>)
       __glibcxx_function_requires(_InputIteratorConcept<_II2>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_valid_range(__first2, __last2);
 
       return std::__lexicographical_compare_impl
 	(__first1, __last1, __first2, __last2,
@@ -1289,7 +1319,6 @@
       __glibcxx_function_requires(_EqualOpConcept<
 	    typename iterator_traits<_InputIterator1>::value_type,
 	    typename iterator_traits<_InputIterator2>::value_type>)
-      __glibcxx_requires_valid_range(__first1, __last1);
 
       return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2,
 			     __gnu_cxx::__ops::__iter_equal_to_iter());
@@ -1320,7 +1349,6 @@
       // concept requirements
       __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
       __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_requires_valid_range(__first1, __last1);
 
       return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2,
 	__gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
@@ -1369,8 +1397,6 @@
       __glibcxx_function_requires(_EqualOpConcept<
 	    typename iterator_traits<_InputIterator1>::value_type,
 	    typename iterator_traits<_InputIterator2>::value_type>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_valid_range(__first2, __last2);
 
       return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2,
 			     __gnu_cxx::__ops::__iter_equal_to_iter());
@@ -1403,8 +1429,6 @@
       // concept requirements
       __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>)
       __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>)
-      __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_valid_range(__first2, __last2);
 
       return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2,
 			     __gnu_cxx::__ops::__iter_comp_iter(__binary_pred));
@@ -1421,4 +1445,8 @@
 # include <parallel/algobase.h>
 #endif
 
+#ifdef _GLIBCXX_DEBUG
+# include <debug/algobase.h>
 #endif
+
+#endif
Index: include/bits/c++config
===================================================================
--- include/bits/c++config	(revision 205497)
+++ include/bits/c++config	(working copy)
@@ -149,6 +149,7 @@
     namespace __parallel { }
     namespace __profile { }
     namespace __cxx1998 { }
+    namespace __cxx1998_a { }
 
     namespace __detail { }
 
@@ -255,6 +256,13 @@
 #endif
   }
 
+  namespace __cxx1998_a
+  {
+#if _GLIBCXX_INLINE_VERSION
+ inline namespace __7 { }
+#endif
+  }
+
   // Inline namespace for debug mode.
 # ifdef _GLIBCXX_DEBUG
   inline namespace __debug { }
@@ -309,8 +317,8 @@
 # define _GLIBCXX_EXTERN_TEMPLATE -1
 #endif
 
-#ifdef _GLIBCXX_PARALLEL
-# define _GLIBCXX_STD_A __cxx1998
+#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL)
+# define _GLIBCXX_STD_A __cxx1998_a
 # define _GLIBCXX_BEGIN_NAMESPACE_ALGO \
 	 namespace _GLIBCXX_STD_A { _GLIBCXX_BEGIN_NAMESPACE_VERSION
 # define _GLIBCXX_END_NAMESPACE_ALGO \

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]