public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* PR libstdc++/68222 Hide safe iterator operators
@ 2018-08-02 20:16 François Dumont
  2018-08-07 13:47 ` Jonathan Wakely
  2018-08-07 22:39 ` Jonathan Wakely
  0 siblings, 2 replies; 8+ messages in thread
From: François Dumont @ 2018-08-02 20:16 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1079 bytes --]

Hi

     Here is a patch to avoid definition of invalid operators on the 
Debug mode safe iterator type depending on its category.

     Even if it is limited to the Debug mode code I would like to have a 
feedback before committing. Especially on the following points:

- _Safe_tagged_iterator: Is the name ok ?

- Inheritance between the different _Safe_tagged_iterator 
instantiations. I am already working on making the operators friends as 
we discuss in another thread so I might review this design at this moment.

- Are concept checks I added to testsuite_containers.h citerator ok ?

     This patch also does some cleanup on Debug functions. 
__check_dereferenceable was not used (anymore maybe) so I removed it. I 
also prefer to take iterator by value in the fallback implementations 
like it is done in std algos. Only _Safe_tagged_iterator are taken by 
lvalue ref as they are quite expensive to copy (mutex lock).

     I also attach the ChangeLog entry which is quite big.

Tested under Linux x86_64 Debug mode.

François



[-- Attachment #2: safe_iterator.patch --]
[-- Type: text/x-patch, Size: 76687 bytes --]

diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque
index 93b82cf..213e23b 100644
--- a/libstdc++-v3/include/debug/deque
+++ b/libstdc++-v3/include/debug/deque
@@ -57,12 +57,14 @@ namespace __debug
       typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
 
     public:
+      typedef _Base					normal_type;
+
       typedef typename _Base::reference			reference;
       typedef typename _Base::const_reference		const_reference;
 
-      typedef __gnu_debug::_Safe_iterator<_Base_iterator, deque>
+      typedef __gnu_debug::_Safe_tagged_iterator<_Base_iterator, deque>
 							iterator;
-      typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, deque>
+      typedef __gnu_debug::_Safe_tagged_iterator<_Base_const_iterator, deque>
 							const_iterator;
 
       typedef typename _Base::size_type			size_type;
diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h
index 7b3c30b..33bc2b2 100644
--- a/libstdc++-v3/include/debug/formatter.h
+++ b/libstdc++-v3/include/debug/formatter.h
@@ -76,8 +76,8 @@ namespace __gnu_debug
 
   class _Safe_sequence_base;
 
-  template<typename _Iterator, typename _Sequence>
-    class _Safe_iterator;
+  template<typename _Iterator, typename _Sequence, typename _Category>
+    class _Safe_tagged_iterator;
 
   template<typename _Iterator, typename _Sequence>
     class _Safe_local_iterator;
@@ -264,8 +264,9 @@ namespace __gnu_debug
 	_M_variant._M_string._M_value = __value;
       }
 
-      template<typename _Iterator, typename _Sequence>
-	_Parameter(_Safe_iterator<_Iterator, _Sequence> const& __it,
+      template<typename _Iterator, typename _Sequence, typename _Category>
+	_Parameter(_Safe_tagged_iterator<_Iterator, _Sequence,
+					 _Category> const& __it,
 		   const char* __name, _Is_iterator)
 	: _M_kind(__iterator),  _M_variant()
 	{
@@ -379,9 +380,10 @@ namespace __gnu_debug
 	    = _S_reverse_state(_M_variant._M_iterator._M_state);
 	}
 
-      template<typename _Iterator, typename _Sequence>
-	_Parameter(std::reverse_iterator<_Safe_iterator<_Iterator,
-							_Sequence>> const& __it,
+      template<typename _Iterator, typename _Sequence, typename _Category>
+	_Parameter(
+	  std::reverse_iterator<_Safe_tagged_iterator<_Iterator, _Sequence,
+						      _Category>> const& __it,
 	  const char* __name, _Is_iterator)
 	: _Parameter(__it.base(), __name, _Is_iterator{})
 	{
@@ -397,9 +399,10 @@ namespace __gnu_debug
 	: _Parameter(__it.base(), __name, _Is_iterator{})
 	{ _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); }
 
-      template<typename _Iterator, typename _Sequence>
-	_Parameter(std::move_iterator<_Safe_iterator<_Iterator,
-						     _Sequence>> const& __it,
+      template<typename _Iterator, typename _Sequence, typename _Category>
+	_Parameter(
+	  std::move_iterator<_Safe_tagged_iterator<_Iterator, _Sequence,
+						   _Category>> const& __it,
 	  const char* __name, _Is_iterator)
 	: _Parameter(__it.base(), __name, _Is_iterator{})
       {
diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list
index 633af1a..6b874db 100644
--- a/libstdc++-v3/include/debug/forward_list
+++ b/libstdc++-v3/include/debug/forward_list
@@ -194,12 +194,14 @@ namespace __debug
       typedef typename _Base::const_iterator	_Base_const_iterator;
 
     public:
+      typedef _Base				normal_type;
+
       typedef typename _Base::reference		reference;
       typedef typename _Base::const_reference	const_reference;
 
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	_Base_iterator, forward_list>		iterator;
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	_Base_const_iterator, forward_list>	const_iterator;
 
       typedef typename _Base::size_type		size_type;
diff --git a/libstdc++-v3/include/debug/functions.h b/libstdc++-v3/include/debug/functions.h
index ce501f2..6719703 100644
--- a/libstdc++-v3/include/debug/functions.h
+++ b/libstdc++-v3/include/debug/functions.h
@@ -31,7 +31,9 @@
 
 #include <bits/move.h>		// for __addressof
 #include <bits/stl_function.h>	// for less
+
 #if __cplusplus >= 201103L
+# include <bits/stl_iterator.h>	// for __miter_base
 # include <type_traits>		// for is_lvalue_reference and conditional.
 #endif
 
@@ -64,19 +66,6 @@ namespace __gnu_debug
     __check_singular(const _Tp* __ptr)
     { return __ptr == 0; }
 
-  /** Assume that some arbitrary iterator is dereferenceable, because we
-      can't prove that it isn't. */
-  template<typename _Iterator>
-    inline bool
-    __check_dereferenceable(const _Iterator&)
-    { return true; }
-
-  /** Non-NULL pointers are dereferenceable. */
-  template<typename _Tp>
-    inline bool
-    __check_dereferenceable(const _Tp* __ptr)
-    { return __ptr; }
-
   /* Checks that [first, last) is a valid range, and then returns
    * __first. This routine is useful when we can't use a separate
    * assertion statement because, e.g., we are in a constructor.
@@ -95,9 +84,10 @@ namespace __gnu_debug
     }
 
   /* Handle the case where __other is a pointer to _Sequence::value_type. */
-  template<typename _Iterator, typename _Sequence>
+  template<typename _Iterator, typename _Sequence, typename _Category>
     inline bool
-    __foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>& __it,
+    __foreign_iterator_aux4(const _Safe_tagged_iterator<_Iterator, _Sequence,
+							_Category>& __it,
 			    const typename _Sequence::value_type* __other)
     {
       typedef const typename _Sequence::value_type* _PointerType;
@@ -116,15 +106,18 @@ namespace __gnu_debug
     }
 
   /* Fallback overload for when we can't tell, assume it is valid. */
-  template<typename _Iterator, typename _Sequence>
+  template<typename _Iterator, typename _Sequence, typename _Category>
     inline bool
-    __foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>&, ...)
+    __foreign_iterator_aux4(const _Safe_tagged_iterator<_Iterator, _Sequence,
+							_Category>&, ...)
     { return true; }
 
   /* Handle sequences with contiguous storage */
-  template<typename _Iterator, typename _Sequence, typename _InputIterator>
+  template<typename _Iterator, typename _Sequence, typename _Category,
+	   typename _InputIterator>
     inline bool
-    __foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>& __it,
+    __foreign_iterator_aux3(const _Safe_tagged_iterator<_Iterator, _Sequence,
+							_Category>& __it,
 			    const _InputIterator& __other,
 			    const _InputIterator& __other_end,
 			    std::__true_type)
@@ -137,34 +130,46 @@ namespace __gnu_debug
     }
 
   /* Handle non-contiguous containers, assume it is valid. */
-  template<typename _Iterator, typename _Sequence, typename _InputIterator>
+  template<typename _Iterator, typename _Sequence, typename _Category,
+	   typename _InputIterator>
     inline bool
-    __foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>&,
+    __foreign_iterator_aux3(const _Safe_tagged_iterator<_Iterator, _Sequence,
+							_Category>&,
 			    const _InputIterator&, const _InputIterator&,
 			    std::__false_type)
     { return true; }
 
   /** 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,
-		const _Safe_iterator<_OtherIterator, _Sequence>&)
+  template<typename _Iterator, typename _Sequence, typename _Category,
+	   typename _OtherIterator>
+    inline bool
+    __foreign_iterator_aux2(const _Safe_tagged_iterator<_Iterator, _Sequence,
+							_Category>& __it,
+			    const _Safe_tagged_iterator<_OtherIterator, _Sequence,
+							_Category>& __other,
+			    const _Safe_tagged_iterator<_OtherIterator, _Sequence,
+							_Category>&)
     { return __it._M_get_sequence() != __other._M_get_sequence(); }
 
   /** 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>&)
+  template<typename _Iterator, typename _Sequence, typename _Category,
+	   typename _OtherIterator, typename _OtherSequence,
+	   typename _OtherCategory>
+    inline bool
+    __foreign_iterator_aux2(const _Safe_tagged_iterator<_Iterator, _Sequence,
+							_Category>&,
+	const _Safe_tagged_iterator<_OtherIterator, _OtherSequence,
+				    _OtherCategory>&,
+	const _Safe_tagged_iterator<_OtherIterator, _OtherSequence,
+				    _OtherCategory>&)
     { return true; }
 
   /* Handle non-debug iterators. */
-  template<typename _Iterator, typename _Sequence, typename _InputIterator>
+  template<typename _Iterator, typename _Sequence, typename _Category,
+	   typename _InputIterator>
     inline bool
-    __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
+    __foreign_iterator_aux2(const _Safe_tagged_iterator<_Iterator, _Sequence,
+							_Category>& __it,
 			    const _InputIterator& __other,
 			    const _InputIterator& __other_end)
     {
@@ -181,18 +186,21 @@ namespace __gnu_debug
     }
 
   /* Handle the case where we aren't really inserting a range after all */
-  template<typename _Iterator, typename _Sequence, typename _Integral>
+  template<typename _Iterator, typename _Sequence, typename _Category,
+	   typename _Integral>
     inline bool
-    __foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>&,
+    __foreign_iterator_aux(const _Safe_tagged_iterator<_Iterator, _Sequence,
+						       _Category>&,
 			   _Integral, _Integral,
 			   std::__true_type)
     { return true; }
 
   /* Handle all iterators. */
-  template<typename _Iterator, typename _Sequence,
+  template<typename _Iterator, typename _Sequence, typename _Category,
 	   typename _InputIterator>
     inline bool
-    __foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>& __it,
+    __foreign_iterator_aux(const _Safe_tagged_iterator<_Iterator, _Sequence,
+						       _Category>& __it,
 			   _InputIterator __other, _InputIterator __other_end,
 			   std::__false_type)
     {
@@ -201,10 +209,11 @@ namespace __gnu_debug
 				   std::__miter_base(__other_end));
     }
 
-  template<typename _Iterator, typename _Sequence,
+  template<typename _Iterator, typename _Sequence, typename _Category,
 	   typename _InputIterator>
     inline bool
-    __foreign_iterator(const _Safe_iterator<_Iterator, _Sequence>& __it,
+    __foreign_iterator(const _Safe_tagged_iterator<_Iterator, _Sequence,
+						   _Category>& __it,
 		       _InputIterator __other, _InputIterator __other_end)
     {
       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index 2073df9..67fbd83 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -37,8 +37,13 @@
 
 namespace __gnu_debug
 {
+  template<typename _Iterator, typename _Sequence, typename _Category>
+    class _Safe_tagged_iterator;
+
+#if __cplusplus >= 201103L
   template<typename _Iterator, typename _Sequence>
-    class _Safe_iterator;
+    class _Safe_local_iterator;
+#endif
 
   /** The precision to which we can calculate the distance between
    *  two iterators.
@@ -83,13 +88,13 @@ namespace __gnu_debug
   */
   template<typename _Iterator>
     inline typename _Distance_traits<_Iterator>::__type
-    __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
+    __get_distance(_Iterator __lhs, _Iterator __rhs,
 		   std::random_access_iterator_tag)
     { return std::make_pair(__rhs - __lhs, __dp_exact); }
 
   template<typename _Iterator>
     inline typename _Distance_traits<_Iterator>::__type
-    __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
+    __get_distance(_Iterator __lhs, _Iterator __rhs,
 		   std::input_iterator_tag)
     {
       if (__lhs == __rhs)
@@ -100,16 +105,30 @@ namespace __gnu_debug
 
   template<typename _Iterator>
     inline typename _Distance_traits<_Iterator>::__type
-    __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
+    __get_distance(_Iterator __lhs, _Iterator __rhs)
     { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
 
+  template<typename _Iterator, typename _Sequence, typename _Category>
+    typename _Distance_traits<_Iterator>::__type
+    __get_distance(const _Safe_tagged_iterator<_Iterator, _Sequence,
+					       _Category>&,
+		   const _Safe_tagged_iterator<_Iterator, _Sequence,
+					       _Category>&);
+
+#if __cplusplus >= 201103L
+  template<typename _Iterator, typename _Sequence>
+    typename _Distance_traits<_Iterator>::__type
+    __get_distance(const _Safe_local_iterator<_Iterator, _Sequence>&,
+		   const _Safe_local_iterator<_Iterator, _Sequence>&);
+#endif
+
   /** We say that integral types for a valid range, and defer to other
    *  routines to realize what to do with integral types instead of
    *  iterators.
   */
   template<typename _Integral>
     inline bool
-    __valid_range_aux(const _Integral&, const _Integral&,
+    __valid_range_aux(_Integral, _Integral,
 		      typename _Distance_traits<_Integral>::__type& __dist,
 		      std::__true_type)
     {
@@ -122,8 +141,7 @@ namespace __gnu_debug
   */
   template<typename _InputIterator>
     inline bool
-    __valid_range_aux(const _InputIterator& __first,
-		      const _InputIterator& __last,
+    __valid_range_aux(_InputIterator __first, _InputIterator __last,
 		      typename _Distance_traits<_InputIterator>::__type& __dist,
 		      std::__false_type)
     {
@@ -152,61 +170,73 @@ namespace __gnu_debug
   */
   template<typename _InputIterator>
     inline bool
-    __valid_range(const _InputIterator& __first, const _InputIterator& __last,
+    __valid_range(_InputIterator __first, _InputIterator __last,
 		  typename _Distance_traits<_InputIterator>::__type& __dist)
     {
       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
       return __valid_range_aux(__first, __last, __dist, _Integral());
     }
 
+  template<typename _Iterator, typename _Sequence, typename _Category>
+    bool
+    __valid_range(const _Safe_tagged_iterator<_Iterator, _Sequence,
+					      _Category>&,
+		  const _Safe_tagged_iterator<_Iterator, _Sequence,
+					      _Category>&,
+		  typename _Distance_traits<_Iterator>::__type&);
+
+#if __cplusplus >= 201103L
+  template<typename _Iterator,typename _Sequence>
+    bool
+    __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&,
+		  const _Safe_local_iterator<_Iterator, _Sequence>&,
+		  typename _Distance_traits<_Iterator>::__type&);
+#endif
+
   template<typename _InputIterator>
     inline bool
-    __valid_range(const _InputIterator& __first, const _InputIterator& __last)
+    __valid_range(_InputIterator __first, _InputIterator __last)
     {
       typename _Distance_traits<_InputIterator>::__type __dist;
       return __valid_range(__first, __last, __dist);
     }
 
+  template<typename _Iterator, typename _Sequence, typename _Category>
+    bool
+    __valid_range(const _Safe_tagged_iterator<_Iterator, _Sequence,
+					      _Category>&,
+		  const _Safe_tagged_iterator<_Iterator, _Sequence,
+					      _Category>&);
+
+#if __cplusplus >= 201103L
+  template<typename _Iterator, typename _Sequence>
+    bool
+    __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&,
+		  const _Safe_local_iterator<_Iterator, _Sequence>&);
+#endif
+
   // Fallback method, always ok.
   template<typename _InputIterator, typename _Size>
     inline bool
     __can_advance(_InputIterator, _Size)
     { return true; }
 
-  template<typename _Iterator, typename _Sequence, typename _Size>
+  template<typename _Iterator, typename _Sequence, typename _Category,
+	   typename _Size>
     bool
-    __can_advance(const _Safe_iterator<_Iterator, _Sequence>&, _Size);
-
-#if __cplusplus < 201103L
-  // Helper struct to detect random access safe iterators.
-  template<typename _Iterator>
-    struct __is_safe_random_iterator
-    {
-      enum { __value = 0 };
-      typedef std::__false_type __type;
-    };
-
-  template<typename _Iterator>
-    struct _Siter_base
-    : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
-    { };
+    __can_advance(const _Safe_tagged_iterator<_Iterator, _Sequence, _Category>&,
+		  _Size);
 
   /** Helper function to extract base iterator of random access safe iterator
-      in order to reduce performance impact of debug mode.  Limited to random
-      access iterator because it is the only category for which it is possible
-      to check for correct iterators order in the __valid_range function
-      thanks to the < operator.
+   *  in order to reduce performance impact of debug mode.  Limited to random
+   *  access iterator because it is the only category for which it is possible
+   *  to check for correct iterators order in the __valid_range function
+   *  thanks to the < operator.
    */
   template<typename _Iterator>
-    inline typename _Siter_base<_Iterator>::iterator_type
-    __base(_Iterator __it)
-    { return _Siter_base<_Iterator>::_S_base(__it); }
-#else
-  template<typename _Iterator>
     inline _Iterator
     __base(_Iterator __it)
     { return __it; }
-#endif
 
 #if __cplusplus < 201103L
   template<typename _Iterator>
diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list
index bf3179a..dd91d5d 100644
--- a/libstdc++-v3/include/debug/list
+++ b/libstdc++-v3/include/debug/list
@@ -58,12 +58,14 @@ namespace __debug
       typedef __gnu_debug::_Not_equal_to<_Base_const_iterator>  _Not_equal;
 
     public:
+      typedef _Base					normal_type;
+
       typedef typename _Base::reference			reference;
       typedef typename _Base::const_reference		const_reference;
 
-      typedef __gnu_debug::_Safe_iterator<_Base_iterator, list>
+      typedef __gnu_debug::_Safe_tagged_iterator<_Base_iterator, list>
 							iterator;
-      typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, list>
+      typedef __gnu_debug::_Safe_tagged_iterator<_Base_const_iterator, list>
 							const_iterator;
 
       typedef typename _Base::size_type			size_type;
diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h
index 1fd4416..3d0dba2 100644
--- a/libstdc++-v3/include/debug/map.h
+++ b/libstdc++-v3/include/debug/map.h
@@ -57,6 +57,8 @@ namespace __debug
       typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
 
     public:
+      typedef _Base					normal_type;
+
       // types:
       typedef _Key					key_type;
       typedef _Tp					mapped_type;
@@ -66,9 +68,9 @@ namespace __debug
       typedef typename _Base::reference			reference;
       typedef typename _Base::const_reference		const_reference;
 
-      typedef __gnu_debug::_Safe_iterator<_Base_iterator, map>
+      typedef __gnu_debug::_Safe_tagged_iterator<_Base_iterator, map>
 							iterator;
-      typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, map>
+      typedef __gnu_debug::_Safe_tagged_iterator<_Base_const_iterator, map>
 							const_iterator;
 
       typedef typename _Base::size_type			size_type;
diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h
index 0994dc4..7531130 100644
--- a/libstdc++-v3/include/debug/multimap.h
+++ b/libstdc++-v3/include/debug/multimap.h
@@ -57,6 +57,8 @@ namespace __debug
       typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
 
     public:
+      typedef _Base					normal_type;
+
       // types:
       typedef _Key					key_type;
       typedef _Tp					mapped_type;
@@ -66,10 +68,10 @@ namespace __debug
       typedef typename _Base::reference			reference;
       typedef typename _Base::const_reference		const_reference;
 
-      typedef __gnu_debug::_Safe_iterator<_Base_iterator, multimap>
+      typedef __gnu_debug::_Safe_tagged_iterator<_Base_iterator, multimap>
 							iterator;
-      typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
-					  multimap>	const_iterator;
+      typedef __gnu_debug::_Safe_tagged_iterator<_Base_const_iterator, multimap>
+							const_iterator;
 
       typedef typename _Base::size_type			size_type;
       typedef typename _Base::difference_type		difference_type;
diff --git a/libstdc++-v3/include/debug/multiset.h b/libstdc++-v3/include/debug/multiset.h
index 6e4c1b0..b1ed3ca 100644
--- a/libstdc++-v3/include/debug/multiset.h
+++ b/libstdc++-v3/include/debug/multiset.h
@@ -56,6 +56,8 @@ namespace __debug
       typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
 
     public:
+      typedef _Base					normal_type;
+
       // types:
       typedef _Key					key_type;
       typedef _Key					value_type;
@@ -65,10 +67,10 @@ namespace __debug
       typedef typename _Base::reference			reference;
       typedef typename _Base::const_reference		const_reference;
 
-      typedef __gnu_debug::_Safe_iterator<_Base_iterator, multiset>
+      typedef __gnu_debug::_Safe_tagged_iterator<_Base_iterator, multiset>
 							iterator;
-      typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
-					  multiset>	const_iterator;
+      typedef __gnu_debug::_Safe_tagged_iterator<_Base_const_iterator, multiset>
+							const_iterator;
 
       typedef typename _Base::size_type			size_type;
       typedef typename _Base::difference_type		difference_type;
diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h
index b8256fc..430852c 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -38,6 +38,9 @@
 
 namespace __gnu_debug
 {
+  template<typename _Iterator, typename _Sequence>
+    class _Safe_iterator;
+
   /** Helper struct to deal with sequence offering a before_begin
    *  iterator.
    **/
@@ -76,7 +79,6 @@ namespace __gnu_debug
    *  %_Safe_iterator has member functions for iterator invalidation,
    *  attaching/detaching the iterator from sequences, and querying
    *  the iterator's state.
-   *
    *  Note that _Iterator must be the first base class so that it gets
    *  initialized before the iterator is being attached to the container's list
    *  of iterators and it is being detached before _Iterator get
@@ -89,10 +91,10 @@ namespace __gnu_debug
     {
       typedef _Iterator _Iter_base;
       typedef _Safe_iterator_base _Safe_base;
-      typedef typename _Sequence::const_iterator _Const_iterator;
 
       typedef std::iterator_traits<_Iterator> _Traits;
 
+    protected:
       struct _Attach_single
       { };
 
@@ -173,7 +175,7 @@ namespace __gnu_debug
 	_Safe_iterator(
 	  const _Safe_iterator<_MutableIterator,
 	  typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
-		      typename _Sequence::iterator::iterator_type>::__value),
+			typename _Sequence::normal_type::iterator>::__value),
 		   _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT
 	: _Iter_base(__x.base())
 	{
@@ -279,19 +281,306 @@ namespace __gnu_debug
 	return base().operator->();
       }
 
+      // ------ Utilities ------
+
+      /// Determine if this is a constant iterator.
+      static bool
+      _S_constant()
+      {
+	return std::__are_same<typename _Sequence::normal_type::const_iterator,
+			       _Iterator>::__value;
+      }
+
+      /**
+       * @brief Return the underlying iterator
+       */
+      _Iterator&
+      base() _GLIBCXX_NOEXCEPT { return *this; }
+
+      const _Iterator&
+      base() const _GLIBCXX_NOEXCEPT { return *this; }
+
+      /**
+       * @brief Conversion to underlying non-debug iterator to allow
+       * better interaction with non-debug containers.
+       */
+      operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; }
+
+      /** Attach iterator to the given sequence. */
+      void
+      _M_attach(_Safe_sequence_base* __seq)
+      { _Safe_base::_M_attach(__seq, _S_constant()); }
+
+      /** Likewise, but not thread-safe. */
+      void
+      _M_attach_single(_Safe_sequence_base* __seq)
+      { _Safe_base::_M_attach_single(__seq, _S_constant()); }
+
+      /// Is the iterator dereferenceable?
+      bool
+      _M_dereferenceable() const
+      { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
+
+      /// Is the iterator before a dereferenceable one?
+      bool
+      _M_before_dereferenceable() const
+      {
+	if (this->_M_incrementable())
+	{
+	  _Iterator __base = base();
+	  return ++__base != _M_get_sequence()->_M_base().end();
+	}
+	return false;
+      }
+
+      /// Is the iterator incrementable?
+      bool
+      _M_incrementable() const
+      { return !this->_M_singular() && !_M_is_end(); }
+
+      // Can we advance the iterator @p __n steps (@p __n may be negative)
+      bool
+      _M_can_advance(const difference_type& __n) const;
+
+      // Is the iterator range [*this, __rhs) valid?
+      bool
+      _M_valid_range(const _Safe_iterator& __rhs,
+		     std::pair<difference_type, _Distance_precision>& __dist,
+		     bool __check_dereferenceable = true) const;
+
+      // The sequence this iterator references.
+      typename __gnu_cxx::__conditional_type<
+	std::__are_same<typename _Sequence::normal_type::const_iterator,
+			_Iterator>::__value,
+	const _Sequence*,
+	_Sequence*>::__type
+      _M_get_sequence() const
+      { return static_cast<_Sequence*>(_M_sequence); }
+
+      /// Is this iterator equal to the sequence's begin() iterator?
+      bool
+      _M_is_begin() const
+      { return base() == _M_get_sequence()->_M_base().begin(); }
+
+      /// Is this iterator equal to the sequence's end() iterator?
+      bool
+      _M_is_end() const
+      { return base() == _M_get_sequence()->_M_base().end(); }
+
+      /// Is this iterator equal to the sequence's before_begin() iterator if
+      /// any?
+      bool
+      _M_is_before_begin() const
+      { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); }
+
+      /// Is this iterator equal to the sequence's before_begin() iterator if
+      /// any or begin() otherwise?
+      bool
+      _M_is_beginnest() const
+      { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); }
+    };
+
+  template<typename _Iterator, typename _Sequence, typename
+	   = typename std::iterator_traits<_Iterator>::iterator_category>
+    class _Safe_tagged_iterator;
+
+  template<typename _Iterator, typename _Sequence>
+    class _Safe_tagged_iterator<_Iterator, _Sequence, std::forward_iterator_tag>
+    : public _Safe_iterator<_Iterator, _Sequence>
+    {
+      typedef _Safe_iterator<_Iterator, _Sequence> _Safe_base;
+
+    protected:
+      typedef typename _Safe_base::_Attach_single _Attach_single;
+
+      _Safe_tagged_iterator(const _Iterator& __i, _Safe_sequence_base* __seq,
+			    _Attach_single)
+      _GLIBCXX_NOEXCEPT
+	: _Safe_base(__i, __seq, _Attach_single())
+      { }
+
+    public:
+      /// @post the iterator is singular and unattached
+      _Safe_tagged_iterator() _GLIBCXX_NOEXCEPT { }
+
+      /**
+       * @brief Safe iterator construction from an unsafe iterator and
+       * its sequence.
+       *
+       * @pre @p seq is not NULL
+       * @post this is not singular
+       */
+      _Safe_tagged_iterator(const _Iterator& __i, const _Safe_sequence_base* __seq)
+      _GLIBCXX_NOEXCEPT
+      : _Safe_base(__i, __seq)
+      { }
+
+      /**
+       * @brief Copy construction.
+       */
+      _Safe_tagged_iterator(const _Safe_tagged_iterator& __x) _GLIBCXX_NOEXCEPT
+      : _Safe_base(__x)
+      { }
+
+#if __cplusplus >= 201103L
+      /** @brief Move construction. */
+      _Safe_tagged_iterator(_Safe_tagged_iterator&&) = default;
+#endif
+
+      /**
+       *  @brief Converting constructor from a mutable iterator to a
+       *  constant iterator.
+      */
+      template<typename _MutableIterator>
+	_Safe_tagged_iterator(
+	  const _Safe_tagged_iterator<_MutableIterator,
+	  typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
+			typename _Sequence::normal_type::iterator>::__value),
+		   _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT
+	: _Safe_base(__x)
+        { }
+
+#if __cplusplus >= 201103L
+      /** @brief Copy assignment. */
+      _Safe_tagged_iterator&
+      operator=(const _Safe_tagged_iterator&) = default;
+
+      /** @brief Move assignment. */
+      _Safe_tagged_iterator&
+      operator=(_Safe_tagged_iterator&&) = default;
+#else
+      /**
+       * @brief Copy assignment.
+       */
+      _Safe_tagged_iterator&
+      operator=(const _Safe_tagged_iterator& __x) _GLIBCXX_NOEXCEPT
+      {
+	_Safe_base::operator=(__x);
+	return *this;
+      }
+#endif
+
       // ------ Input iterator requirements ------
       /**
        *  @brief Iterator preincrement
        *  @pre iterator is incrementable
        */
-      _Safe_iterator&
+      _Safe_tagged_iterator&
       operator++() _GLIBCXX_NOEXCEPT
       {
 	_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
 			      _M_message(__msg_bad_inc)
 			      ._M_iterator(*this, "this"));
 	__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
-	++base();
+	++this->base();
+	return *this;
+      }
+
+      /**
+       *  @brief Iterator postincrement
+       *  @pre iterator is incrementable
+       */
+      _Safe_tagged_iterator
+      operator++(int) _GLIBCXX_NOEXCEPT
+      {
+	_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
+			      _M_message(__msg_bad_inc)
+			      ._M_iterator(*this, "this"));
+	__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+	return _Safe_tagged_iterator(this->base()++, this->_M_sequence,
+				  _Attach_single());
+      }
+    };
+
+  template<typename _Iterator, typename _Sequence>
+    class _Safe_tagged_iterator<_Iterator, _Sequence,
+				std::bidirectional_iterator_tag>
+    : public _Safe_tagged_iterator<_Iterator, _Sequence,
+				   std::forward_iterator_tag>
+    {
+      typedef _Safe_tagged_iterator<_Iterator, _Sequence,
+				    std::forward_iterator_tag> _Safe_base;
+
+    protected:
+      typedef typename _Safe_base::_Attach_single _Attach_single;
+
+      _Safe_tagged_iterator(const _Iterator& __i, _Safe_sequence_base* __seq,
+			    _Attach_single)
+      _GLIBCXX_NOEXCEPT
+	: _Safe_base(__i, __seq, _Attach_single())
+      { }
+
+    public:
+      /// @post the iterator is singular and unattached
+      _Safe_tagged_iterator() _GLIBCXX_NOEXCEPT { }
+
+      /**
+       * @brief Safe iterator construction from an unsafe iterator and
+       * its sequence.
+       *
+       * @pre @p seq is not NULL
+       * @post this is not singular
+       */
+      _Safe_tagged_iterator(const _Iterator& __i,
+			    const _Safe_sequence_base* __seq)
+      _GLIBCXX_NOEXCEPT
+	: _Safe_base(__i, __seq)
+      { }
+
+      /**
+       * @brief Copy construction.
+       */
+      _Safe_tagged_iterator(const _Safe_tagged_iterator& __x) _GLIBCXX_NOEXCEPT
+	: _Safe_base(__x)
+      { }
+
+#if __cplusplus >= 201103L
+      /** @brief Move construction. */
+      _Safe_tagged_iterator(_Safe_tagged_iterator&&) = default;
+#endif
+
+      /**
+       *  @brief Converting constructor from a mutable iterator to a
+       *  constant iterator.
+      */
+      template<typename _MutableIterator>
+	_Safe_tagged_iterator(
+	  const _Safe_tagged_iterator<_MutableIterator,
+	  typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
+			typename _Sequence::normal_type::iterator>::__value),
+		   _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT
+	  : _Safe_base(__x)
+        { }
+
+#if __cplusplus >= 201103L
+      /** @brief Copy assignment. */
+      _Safe_tagged_iterator&
+      operator=(const _Safe_tagged_iterator&) = default;
+
+      /** @brief Move assignment. */
+      _Safe_tagged_iterator&
+      operator=(_Safe_tagged_iterator&&) = default;
+#else
+      /**
+       * @brief Copy assignment.
+       */
+      _Safe_tagged_iterator&
+      operator=(const _Safe_tagged_iterator& __x) _GLIBCXX_NOEXCEPT
+      {
+	_Safe_base::operator=(__x);
+	return *this;
+      }
+#endif
+
+      // ------ Input iterator requirements ------
+      /**
+       *  @brief Iterator preincrement
+       *  @pre iterator is incrementable
+       */
+      _Safe_tagged_iterator&
+      operator++() _GLIBCXX_NOEXCEPT
+      {
+	_Safe_base::operator++();
 	return *this;
       }
 
@@ -299,14 +588,15 @@ namespace __gnu_debug
        *  @brief Iterator postincrement
        *  @pre iterator is incrementable
        */
-      _Safe_iterator
+      _Safe_tagged_iterator
       operator++(int) _GLIBCXX_NOEXCEPT
       {
 	_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
 			      _M_message(__msg_bad_inc)
 			      ._M_iterator(*this, "this"));
 	__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
-	return _Safe_iterator(base()++, this->_M_sequence, _Attach_single());
+	return _Safe_tagged_iterator(this->base()++, this->_M_sequence,
+				     _Attach_single());
       }
 
       // ------ Bidirectional iterator requirements ------
@@ -314,14 +604,157 @@ namespace __gnu_debug
        *  @brief Iterator predecrement
        *  @pre iterator is decrementable
        */
-      _Safe_iterator&
+      _Safe_tagged_iterator&
       operator--() _GLIBCXX_NOEXCEPT
       {
 	_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
 			      _M_message(__msg_bad_dec)
 			      ._M_iterator(*this, "this"));
 	__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
-	--base();
+	--this->base();
+	return *this;
+      }
+
+      /**
+       *  @brief Iterator postdecrement
+       *  @pre iterator is decrementable
+       */
+      _Safe_tagged_iterator
+      operator--(int) _GLIBCXX_NOEXCEPT
+      {
+	_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
+			      _M_message(__msg_bad_dec)
+			      ._M_iterator(*this, "this"));
+	__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+	return _Safe_tagged_iterator(this->base()--, this->_M_sequence,
+				     _Attach_single());
+      }
+
+      // ------ Utilities ------
+
+      // Is the iterator decrementable?
+      bool
+      _M_decrementable() const { return !this->_M_singular() && !this->_M_is_begin(); }
+    };
+
+  template<typename _Iterator, typename _Sequence>
+    class _Safe_tagged_iterator<_Iterator, _Sequence,
+				std::random_access_iterator_tag>
+    : public _Safe_tagged_iterator<_Iterator, _Sequence,
+				   std::bidirectional_iterator_tag>
+    {
+      typedef _Safe_tagged_iterator<_Iterator, _Sequence,
+				    std::bidirectional_iterator_tag> _Safe_base;
+
+      typedef typename _Safe_base::_Attach_single _Attach_single;
+
+      _Safe_tagged_iterator(const _Iterator& __i, _Safe_sequence_base* __seq,
+			    _Attach_single)
+      _GLIBCXX_NOEXCEPT
+	: _Safe_base(__i, __seq, _Attach_single())
+      { }
+
+    public:
+      typedef typename _Safe_base::difference_type	difference_type;
+      typedef typename _Safe_base::reference		reference;
+
+      /// @post the iterator is singular and unattached
+      _Safe_tagged_iterator() _GLIBCXX_NOEXCEPT { }
+
+      /**
+       * @brief Safe iterator construction from an unsafe iterator and
+       * its sequence.
+       *
+       * @pre @p seq is not NULL
+       * @post this is not singular
+       */
+      _Safe_tagged_iterator(const _Iterator& __i,
+			    const _Safe_sequence_base* __seq)
+      _GLIBCXX_NOEXCEPT
+	: _Safe_base(__i, __seq)
+      { }
+
+      /**
+       * @brief Copy construction.
+       */
+      _Safe_tagged_iterator(const _Safe_tagged_iterator& __x) _GLIBCXX_NOEXCEPT
+	: _Safe_base(__x)
+      { }
+
+#if __cplusplus >= 201103L
+      /** @brief Move construction. */
+      _Safe_tagged_iterator(_Safe_tagged_iterator&&) = default;
+#endif
+
+      /**
+       *  @brief Converting constructor from a mutable iterator to a
+       *  constant iterator.
+      */
+      template<typename _MutableIterator>
+	_Safe_tagged_iterator(
+	  const _Safe_tagged_iterator<_MutableIterator,
+	  typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
+			typename _Sequence::normal_type::iterator>::__value),
+		   _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT
+	  : _Safe_base(__x)
+        { }
+
+#if __cplusplus >= 201103L
+      /** @brief Copy assignment. */
+      _Safe_tagged_iterator&
+      operator=(const _Safe_tagged_iterator&) = default;
+
+      /** @brief Move assignment. */
+      _Safe_tagged_iterator&
+      operator=(_Safe_tagged_iterator&&) = default;
+#else
+      /**
+       * @brief Copy assignment.
+       */
+      _Safe_tagged_iterator&
+      operator=(const _Safe_tagged_iterator& __x) _GLIBCXX_NOEXCEPT
+      {
+	_Safe_base::operator=(__x);
+	return *this;
+      }
+#endif
+
+      // ------ Input iterator requirements ------
+      /**
+       *  @brief Iterator preincrement
+       *  @pre iterator is incrementable
+       */
+      _Safe_tagged_iterator&
+      operator++() _GLIBCXX_NOEXCEPT
+      {
+	_Safe_base::operator++();
+	return *this;
+      }
+
+      /**
+       *  @brief Iterator postincrement
+       *  @pre iterator is incrementable
+       */
+      _Safe_tagged_iterator
+      operator++(int) _GLIBCXX_NOEXCEPT
+      {
+	_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
+			      _M_message(__msg_bad_inc)
+			      ._M_iterator(*this, "this"));
+	__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+	return _Safe_tagged_iterator(this->base()++, this->_M_sequence,
+				     _Attach_single());
+      }
+
+      // ------ Bidirectional iterator requirements ------
+      /**
+       *  @brief Iterator predecrement
+       *  @pre iterator is decrementable
+       */
+      _Safe_tagged_iterator&
+      operator--() _GLIBCXX_NOEXCEPT
+      {
+	_Safe_base::operator--();
 	return *this;
       }
 
@@ -329,14 +762,15 @@ namespace __gnu_debug
        *  @brief Iterator postdecrement
        *  @pre iterator is decrementable
        */
-      _Safe_iterator
+      _Safe_tagged_iterator
       operator--(int) _GLIBCXX_NOEXCEPT
       {
 	_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
 			      _M_message(__msg_bad_dec)
 			      ._M_iterator(*this, "this"));
 	__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
-	return _Safe_iterator(base()--, this->_M_sequence, _Attach_single());
+	return _Safe_tagged_iterator(this->base()--, this->_M_sequence,
+				     _Attach_single());
       }
 
       // ------ Random access iterator requirements ------
@@ -347,153 +781,54 @@ namespace __gnu_debug
 			      && this->_M_can_advance(__n + 1),
 			      _M_message(__msg_iter_subscript_oob)
 			      ._M_iterator(*this)._M_integer(__n));
-	return base()[__n];
+	return this->base()[__n];
       }
 
-      _Safe_iterator&
+      _Safe_tagged_iterator&
       operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT
       {
 	_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
 			      _M_message(__msg_advance_oob)
 			      ._M_iterator(*this)._M_integer(__n));
 	__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
-	base() += __n;
+	this->base() += __n;
 	return *this;
       }
 
-      _Safe_iterator
+      _Safe_tagged_iterator
       operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT
       {
 	_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
 			      _M_message(__msg_advance_oob)
 			      ._M_iterator(*this)._M_integer(__n));
-	return _Safe_iterator(base() + __n, this->_M_sequence);
+	return _Safe_tagged_iterator(this->base() + __n, this->_M_sequence);
       }
 
-      _Safe_iterator&
+      _Safe_tagged_iterator&
       operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT
       {
 	_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
 			      _M_message(__msg_retreat_oob)
 			      ._M_iterator(*this)._M_integer(__n));
 	__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
-	base() -= __n;
+	this->base() -= __n;
 	return *this;
       }
 
-      _Safe_iterator
+      _Safe_tagged_iterator
       operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT
       {
 	_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
 			      _M_message(__msg_retreat_oob)
 			      ._M_iterator(*this)._M_integer(__n));
-	return _Safe_iterator(base() - __n, this->_M_sequence);
-      }
-
-      // ------ Utilities ------
-
-      /// Determine if this is a constant iterator.
-      static bool
-      _S_constant()
-      { return std::__are_same<_Const_iterator, _Safe_iterator>::__value; }
-
-      /**
-       * @brief Return the underlying iterator
-       */
-      _Iterator&
-      base() _GLIBCXX_NOEXCEPT { return *this; }
-
-      const _Iterator&
-      base() const _GLIBCXX_NOEXCEPT { return *this; }
-
-      /**
-       * @brief Conversion to underlying non-debug iterator to allow
-       * better interaction with non-debug containers.
-       */
-      operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; }
-
-      /** Attach iterator to the given sequence. */
-      void
-      _M_attach(_Safe_sequence_base* __seq)
-      { _Safe_base::_M_attach(__seq, _S_constant()); }
-
-      /** Likewise, but not thread-safe. */
-      void
-      _M_attach_single(_Safe_sequence_base* __seq)
-      { _Safe_base::_M_attach_single(__seq, _S_constant()); }
-
-      /// Is the iterator dereferenceable?
-      bool
-      _M_dereferenceable() const
-      { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
-
-      /// Is the iterator before a dereferenceable one?
-      bool
-      _M_before_dereferenceable() const
-      {
-	if (this->_M_incrementable())
-	{
-	  _Iterator __base = base();
-	  return ++__base != _M_get_sequence()->_M_base().end();
+	return _Safe_tagged_iterator(this->base() - __n, this->_M_sequence);
       }
-	return false;
-      }
-
-      /// Is the iterator incrementable?
-      bool
-      _M_incrementable() const
-      { return !this->_M_singular() && !_M_is_end(); }
-
-      // Is the iterator decrementable?
-      bool
-      _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
-
-      // Can we advance the iterator @p __n steps (@p __n may be negative)
-      bool
-      _M_can_advance(const difference_type& __n) const;
-
-      // Is the iterator range [*this, __rhs) valid?
-      bool
-      _M_valid_range(const _Safe_iterator& __rhs,
-		     std::pair<difference_type, _Distance_precision>& __dist,
-		     bool __check_dereferenceable = true) const;
-
-      // The sequence this iterator references.
-      typename
-      __gnu_cxx::__conditional_type<std::__are_same<_Const_iterator,
-						    _Safe_iterator>::__value,
-				    const _Sequence*,
-				    _Sequence*>::__type
-      _M_get_sequence() const
-      { return static_cast<_Sequence*>(_M_sequence); }
-
-      /// Is this iterator equal to the sequence's begin() iterator?
-      bool
-      _M_is_begin() const
-      { return base() == _M_get_sequence()->_M_base().begin(); }
-
-      /// Is this iterator equal to the sequence's end() iterator?
-      bool
-      _M_is_end() const
-      { return base() == _M_get_sequence()->_M_base().end(); }
-
-      /// Is this iterator equal to the sequence's before_begin() iterator if
-      /// any?
-      bool
-      _M_is_before_begin() const
-      { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); }
-
-      /// Is this iterator equal to the sequence's before_begin() iterator if
-      /// any or begin() otherwise?
-      bool
-      _M_is_beginnest() const
-      { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); }
     };
 
   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
     inline bool
-    operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
-	       const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+    operator==(const _Safe_tagged_iterator<_IteratorL, _Sequence>& __lhs,
+	       const _Safe_tagged_iterator<_IteratorR, _Sequence>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -509,8 +844,8 @@ namespace __gnu_debug
 
   template<typename _Iterator, typename _Sequence>
     inline bool
-    operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
-	       const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+    operator==(const _Safe_tagged_iterator<_Iterator, _Sequence>& __lhs,
+	       const _Safe_tagged_iterator<_Iterator, _Sequence>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -526,8 +861,8 @@ namespace __gnu_debug
 
   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
     inline bool
-    operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
-	       const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+    operator!=(const _Safe_tagged_iterator<_IteratorL, _Sequence>& __lhs,
+	       const _Safe_tagged_iterator<_IteratorR, _Sequence>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -543,8 +878,8 @@ namespace __gnu_debug
 
   template<typename _Iterator, typename _Sequence>
     inline bool
-    operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
-	       const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+    operator!=(const _Safe_tagged_iterator<_Iterator, _Sequence>& __lhs,
+	       const _Safe_tagged_iterator<_Iterator, _Sequence>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -560,8 +895,10 @@ namespace __gnu_debug
 
   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
     inline bool
-    operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
-	      const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+    operator<(const _Safe_tagged_iterator<_IteratorL, _Sequence,
+					std::random_access_iterator_tag>& __lhs,
+	      const _Safe_tagged_iterator<_IteratorR, _Sequence,
+					std::random_access_iterator_tag>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -577,8 +914,10 @@ namespace __gnu_debug
 
   template<typename _Iterator, typename _Sequence>
     inline bool
-    operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
-	      const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+    operator<(const _Safe_tagged_iterator<_Iterator, _Sequence,
+					std::random_access_iterator_tag>& __lhs,
+	      const _Safe_tagged_iterator<_Iterator, _Sequence,
+					std::random_access_iterator_tag>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -594,8 +933,10 @@ namespace __gnu_debug
 
   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
     inline bool
-    operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
-	       const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+    operator<=(const _Safe_tagged_iterator<_IteratorL, _Sequence,
+					std::random_access_iterator_tag>& __lhs,
+	       const _Safe_tagged_iterator<_IteratorR, _Sequence,
+					std::random_access_iterator_tag>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -611,8 +952,10 @@ namespace __gnu_debug
 
   template<typename _Iterator, typename _Sequence>
     inline bool
-    operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
-	       const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+    operator<=(const _Safe_tagged_iterator<_Iterator, _Sequence,
+				    std::random_access_iterator_tag>& __lhs,
+	       const _Safe_tagged_iterator<_Iterator, _Sequence,
+				    std::random_access_iterator_tag>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -628,8 +971,10 @@ namespace __gnu_debug
 
   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
     inline bool
-    operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
-	      const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+    operator>(const _Safe_tagged_iterator<_IteratorL, _Sequence,
+					std::random_access_iterator_tag>& __lhs,
+	      const _Safe_tagged_iterator<_IteratorR, _Sequence,
+					std::random_access_iterator_tag>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -645,8 +990,10 @@ namespace __gnu_debug
 
   template<typename _Iterator, typename _Sequence>
     inline bool
-    operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
-	      const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+    operator>(const _Safe_tagged_iterator<_Iterator, _Sequence,
+					std::random_access_iterator_tag>& __lhs,
+	      const _Safe_tagged_iterator<_Iterator, _Sequence,
+					std::random_access_iterator_tag>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -662,8 +1009,10 @@ namespace __gnu_debug
 
   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
     inline bool
-    operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
-	       const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+    operator>=(const _Safe_tagged_iterator<_IteratorL, _Sequence,
+					std::random_access_iterator_tag>& __lhs,
+	       const _Safe_tagged_iterator<_IteratorR, _Sequence,
+					std::random_access_iterator_tag>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -679,8 +1028,10 @@ namespace __gnu_debug
 
   template<typename _Iterator, typename _Sequence>
     inline bool
-    operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
-	       const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+    operator>=(const _Safe_tagged_iterator<_Iterator, _Sequence,
+					std::random_access_iterator_tag>& __lhs,
+	       const _Safe_tagged_iterator<_Iterator, _Sequence,
+					std::random_access_iterator_tag>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -699,9 +1050,12 @@ namespace __gnu_debug
   // operators but also operator- must accept mixed iterator/const_iterator
   // parameters.
   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
-    inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
-    operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
-	      const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
+    inline typename _Safe_tagged_iterator<_IteratorL, _Sequence,
+			std::random_access_iterator_tag>::difference_type
+    operator-(const _Safe_tagged_iterator<_IteratorL, _Sequence,
+					std::random_access_iterator_tag>& __lhs,
+	      const _Safe_tagged_iterator<_IteratorR, _Sequence,
+					std::random_access_iterator_tag>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -716,9 +1070,12 @@ namespace __gnu_debug
     }
 
   template<typename _Iterator, typename _Sequence>
-     inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
-     operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
-	       const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+    inline typename _Safe_tagged_iterator<_Iterator, _Sequence,
+			std::random_access_iterator_tag>::difference_type
+    operator-(const _Safe_tagged_iterator<_Iterator, _Sequence,
+					std::random_access_iterator_tag>& __lhs,
+	      const _Safe_tagged_iterator<_Iterator, _Sequence,
+					std::random_access_iterator_tag>& __rhs)
     _GLIBCXX_NOEXCEPT
     {
       _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
@@ -733,32 +1090,43 @@ namespace __gnu_debug
     }
 
   template<typename _Iterator, typename _Sequence>
-    inline _Safe_iterator<_Iterator, _Sequence>
-    operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
-	      const _Safe_iterator<_Iterator, _Sequence>& __i) _GLIBCXX_NOEXCEPT
+    inline _Safe_tagged_iterator<_Iterator, _Sequence,
+				 std::random_access_iterator_tag>
+    operator+(typename _Safe_tagged_iterator<_Iterator,_Sequence,
+		std::random_access_iterator_tag>::difference_type __n,
+	      const _Safe_tagged_iterator<_Iterator, _Sequence,
+		std::random_access_iterator_tag>& __i)
+    _GLIBCXX_NOEXCEPT
     { return __i + __n; }
 
-  /** Safe iterators know if they are dereferenceable. */
-  template<typename _Iterator, typename _Sequence>
-    inline bool
-    __check_dereferenceable(const _Safe_iterator<_Iterator, _Sequence>& __x)
-    { return __x._M_dereferenceable(); }
-
   /** Safe iterators know how to check if they form a valid range. */
-  template<typename _Iterator, typename _Sequence>
+  template<typename _Iterator, typename _Sequence, typename _Category>
     inline bool
-    __valid_range(const _Safe_iterator<_Iterator, _Sequence>& __first,
-		  const _Safe_iterator<_Iterator, _Sequence>& __last,
+    __valid_range(const _Safe_tagged_iterator<_Iterator, _Sequence,
+					      _Category>& __first,
+		  const _Safe_tagged_iterator<_Iterator, _Sequence,
+					      _Category>& __last,
 		  typename _Distance_traits<_Iterator>::__type& __dist)
     { return __first._M_valid_range(__last, __dist); }
 
+  template<typename _Iterator, typename _Sequence, typename _Category>
+    inline bool
+    __valid_range(const _Safe_tagged_iterator<_Iterator, _Sequence,
+					      _Category>& __first,
+		  const _Safe_tagged_iterator<_Iterator, _Sequence,
+					      _Category>& __last)
+    {
+      typename _Distance_traits<_Iterator>::__type __dist;
+      return __first._M_valid_range(__last, __dist);
+    }
+
   /** Safe iterators can help to get better distance knowledge. */
   template<typename _Iterator, typename _Sequence>
     inline typename _Distance_traits<_Iterator>::__type
     __get_distance(const _Safe_iterator<_Iterator, _Sequence>& __first,
 		   const _Safe_iterator<_Iterator, _Sequence>& __last,
-		   std::random_access_iterator_tag)
-    { return std::make_pair(__last.base() - __first.base(), __dp_exact); }
+		   std::random_access_iterator_tag __tag)
+    { return __get_distance(__first.base(), __last.base(), __tag); }
 
   template<typename _Iterator, typename _Sequence>
     inline typename _Distance_traits<_Iterator>::__type
@@ -814,6 +1182,23 @@ namespace __gnu_debug
       return std::make_pair(1, __dp_equality);
     }
 
+  template<typename _Iterator, typename _Sequence, typename _Category>
+    inline typename _Distance_traits<_Iterator>::__type
+    __get_distance(const _Safe_tagged_iterator<_Iterator, _Sequence,
+					       _Category>& __lhs,
+		   const _Safe_tagged_iterator<_Iterator, _Sequence,
+					       _Category>& __rhs)
+    { return __get_distance(__lhs, __rhs, _Category()); }
+
+  template<typename _Iterator, typename _Sequence>
+    inline typename _Distance_traits<_Iterator>::__type
+    __get_distance(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
+		   const _Safe_iterator<_Iterator, _Sequence>& __rhs)
+    {
+      return __get_distance(__lhs, __rhs,
+			    std::__iterator_category(__lhs.base()));
+    }
+
   // Get distance from sequence begin to specified iterator.
   template<typename _Iterator, typename _Sequence>
     inline typename _Distance_traits<_Iterator>::__type
@@ -862,47 +1247,29 @@ namespace __gnu_debug
       return __res;
     }
 
-  template<typename _Iterator, typename _Sequence, typename _Size>
+  template<typename _Iterator, typename _Sequence, typename _Category,
+	   typename _Size>
     inline bool
-    __can_advance(const _Safe_iterator<_Iterator, _Sequence>& __it, _Size __n)
+    __can_advance(const _Safe_tagged_iterator<_Iterator, _Sequence,
+					      _Category>& __it,
+		  _Size __n)
     { return __it._M_can_advance(__n); }
 
-#if __cplusplus < 201103L
-  template<typename _Iterator, typename _Sequence>
-    struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
-    : std::__are_same<std::random_access_iterator_tag,
-                      typename std::iterator_traits<_Iterator>::
-		      iterator_category>
-    { };
-#else
   template<typename _Iterator, typename _Sequence>
     _Iterator
-    __base(const _Safe_iterator<_Iterator, _Sequence>& __it,
-	   std::random_access_iterator_tag)
+    __base(const _Safe_tagged_iterator<_Iterator, _Sequence,
+				       std::random_access_iterator_tag>& __it)
     { return __it.base(); }
 
-  template<typename _Iterator, typename _Sequence>
-    const _Safe_iterator<_Iterator, _Sequence>&
-    __base(const _Safe_iterator<_Iterator, _Sequence>& __it,
-	   std::input_iterator_tag)
-    { return __it; }
-
-  template<typename _Iterator, typename _Sequence>
-    auto
-    __base(const _Safe_iterator<_Iterator, _Sequence>& __it)
-    -> decltype(__base(__it, std::__iterator_category(__it)))
-    { return __base(__it, std::__iterator_category(__it)); }
-#endif
-
 #if __cplusplus < 201103L
   template<typename _Iterator, typename _Sequence>
-    struct _Unsafe_type<_Safe_iterator<_Iterator, _Sequence> >
+    struct _Unsafe_type<_Safe_tagged_iterator<_Iterator, _Sequence> >
     { typedef _Iterator _Type; };
 #endif
 
   template<typename _Iterator, typename _Sequence>
     inline _Iterator
-    __unsafe(const _Safe_iterator<_Iterator, _Sequence>& __it)
+    __unsafe(const _Safe_tagged_iterator<_Iterator, _Sequence>& __it)
     { return __it.base(); }
 
 } // namespace __gnu_debug
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h
index f9597a6..cbdd8ff 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.h
+++ b/libstdc++-v3/include/debug/safe_local_iterator.h
@@ -431,13 +431,6 @@ namespace __gnu_debug
       return __lhs.base() != __rhs.base();
     }
 
-  /** Safe local iterators know if they are dereferenceable. */
-  template<typename _Iterator, typename _Sequence>
-    inline bool
-    __check_dereferenceable(const _Safe_local_iterator<_Iterator,
-						       _Sequence>& __x)
-    { return __x._M_dereferenceable(); }
-
   /** Safe local iterators know how to check if they form a valid range. */
   template<typename _Iterator, typename _Sequence>
     inline bool
@@ -446,14 +439,21 @@ namespace __gnu_debug
 		  typename _Distance_traits<_Iterator>::__type& __dist_info)
     { return __first._M_valid_range(__last, __dist_info); }
 
+  template<typename _Iterator, typename _Sequence>
+    inline bool
+    __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
+		  const _Safe_local_iterator<_Iterator, _Sequence>& __last)
+    {
+      typename _Distance_traits<_Iterator>::__type __dist_info;
+      return __first._M_valid_range(__last, __dist_info);
+    }
+
   /** Safe local iterators need a special method to get distance between each
       other. */
   template<typename _Iterator, typename _Sequence>
-    inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
-		     _Distance_precision>
+    inline typename _Distance_traits<_Iterator>::__type
     __get_distance(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
-		   const _Safe_local_iterator<_Iterator, _Sequence>& __last,
-		   std::input_iterator_tag)
+		   const _Safe_local_iterator<_Iterator, _Sequence>& __last)
     {
       if (__first.base() == __last.base())
 	return { 0, __dp_exact };
diff --git a/libstdc++-v3/include/debug/set.h b/libstdc++-v3/include/debug/set.h
index 571cc47..8f3d83a 100644
--- a/libstdc++-v3/include/debug/set.h
+++ b/libstdc++-v3/include/debug/set.h
@@ -56,6 +56,8 @@ namespace __debug
       typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
 
     public:
+      typedef _Base					normal_type;
+
       // types:
       typedef _Key					key_type;
       typedef _Key					value_type;
@@ -65,9 +67,9 @@ namespace __debug
       typedef typename _Base::reference			reference;
       typedef typename _Base::const_reference		const_reference;
 
-      typedef __gnu_debug::_Safe_iterator<_Base_iterator, set>
+      typedef __gnu_debug::_Safe_tagged_iterator<_Base_iterator, set>
 							iterator;
-      typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, set>
+      typedef __gnu_debug::_Safe_tagged_iterator<_Base_const_iterator, set>
 							const_iterator;
 
       typedef typename _Base::size_type			size_type;
diff --git a/libstdc++-v3/include/debug/stl_iterator.h b/libstdc++-v3/include/debug/stl_iterator.h
index f20b000..fd20160 100644
--- a/libstdc++-v3/include/debug/stl_iterator.h
+++ b/libstdc++-v3/include/debug/stl_iterator.h
@@ -52,12 +52,13 @@ namespace __gnu_debug
     __can_advance(const std::reverse_iterator<_Iterator>& __it, _Size __n)
     { return __can_advance(__it.base(), -__n); }
 
-#if __cplusplus < 201103L
-  template<typename _Iterator>
-    struct __is_safe_random_iterator<std::reverse_iterator<_Iterator> >
-      : __is_safe_random_iterator<_Iterator>
-    { };
+  template<typename _Iterator, typename _Sequence>
+    inline std::reverse_iterator<_Iterator>
+    __base(const std::reverse_iterator<_Safe_tagged_iterator<
+	     _Iterator, _Sequence, std::random_access_iterator_tag> >& __it)
+    { return std::reverse_iterator<_Iterator>(__it.base().base()); }
 
+#if __cplusplus < 201103L
   template<typename _Iterator>
     struct _Unsafe_type<std::reverse_iterator<_Iterator> >
     {
@@ -75,12 +76,6 @@ namespace __gnu_debug
 #else
   template<typename _Iterator>
     inline auto
-    __base(const std::reverse_iterator<_Iterator>& __it)
-    -> decltype(std::__make_reverse_iterator(__base(__it.base())))
-    { return std::__make_reverse_iterator(__base(__it.base())); }
-
-  template<typename _Iterator>
-    inline auto
     __unsafe(const std::reverse_iterator<_Iterator>& __it)
     -> decltype(std::__make_reverse_iterator(__unsafe(__it.base())))
     { return std::__make_reverse_iterator(__unsafe(__it.base())); }
@@ -124,11 +119,12 @@ namespace std
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
-  template<typename _Iterator, typename _Container, typename _Sequence>
+  template<typename _Iterator, typename _Container, typename _Sequence,
+	   typename _Category>
     _Iterator
-    __niter_base(const __gnu_debug::_Safe_iterator<
+    __niter_base(const __gnu_debug::_Safe_tagged_iterator<
 		 __gnu_cxx::__normal_iterator<_Iterator, _Container>,
-		 _Sequence>&);
+		 _Sequence, _Category>&);
 
 _GLIBCXX_END_NAMESPACE_VERSION
 }
diff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string
index 7fa39e3..3d936ce 100644
--- a/libstdc++-v3/include/debug/string
+++ b/libstdc++-v3/include/debug/string
@@ -95,6 +95,8 @@ namespace __gnu_debug
       _Safe;
 
     public:
+      typedef _Base					normal_type;
+
       // types:
       typedef _Traits					traits_type;
       typedef typename _Traits::char_type		value_type;
@@ -106,9 +108,9 @@ namespace __gnu_debug
       typedef typename _Base::pointer			pointer;
       typedef typename _Base::const_pointer		const_pointer;
 
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	typename _Base::iterator, basic_string>		iterator;
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	typename _Base::const_iterator, basic_string>	const_iterator;
 
       typedef std::reverse_iterator<iterator>		reverse_iterator;
diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map
index e4f7c5c..bfc7203 100644
--- a/libstdc++-v3/include/debug/unordered_map
+++ b/libstdc++-v3/include/debug/unordered_map
@@ -67,6 +67,8 @@ namespace __debug
       typedef typename _Base::local_iterator	_Base_local_iterator;
 
     public:
+      typedef _Base					normal_type;
+
       typedef typename _Base::size_type			size_type;
       typedef typename _Base::hasher			hasher;
       typedef typename _Base::key_equal			key_equal;
@@ -75,9 +77,9 @@ namespace __debug
       typedef typename _Base::key_type			key_type;
       typedef typename _Base::value_type		value_type;
 
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	_Base_iterator, unordered_map>			iterator;
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	_Base_const_iterator, unordered_map>		const_iterator;
       typedef __gnu_debug::_Safe_local_iterator<
 	_Base_local_iterator, unordered_map>		local_iterator;
@@ -753,6 +755,8 @@ namespace __debug
       typedef typename _Base::local_iterator	   _Base_local_iterator;
 
     public:
+      typedef _Base					normal_type;
+
       typedef typename _Base::size_type			size_type;
       typedef typename _Base::hasher			hasher;
       typedef typename _Base::key_equal			key_equal;
@@ -761,9 +765,9 @@ namespace __debug
       typedef typename _Base::key_type			key_type;
       typedef typename _Base::value_type		value_type;
 
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	_Base_iterator, unordered_multimap>		iterator;
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	_Base_const_iterator, unordered_multimap>	const_iterator;
       typedef __gnu_debug::_Safe_local_iterator<
 	_Base_local_iterator, unordered_multimap>	local_iterator;
diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set
index adafdb7..586bd18 100644
--- a/libstdc++-v3/include/debug/unordered_set
+++ b/libstdc++-v3/include/debug/unordered_set
@@ -67,6 +67,8 @@ namespace __debug
       typedef typename _Base::local_iterator	   _Base_local_iterator;
 
     public:
+      typedef _Base					normal_type;
+
       typedef typename _Base::size_type			size_type;
       typedef typename _Base::hasher			hasher;
       typedef typename _Base::key_equal			key_equal;
@@ -75,9 +77,9 @@ namespace __debug
       typedef typename _Base::key_type			key_type;
       typedef typename _Base::value_type		value_type;
 
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	_Base_iterator, unordered_set>			iterator;
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	_Base_const_iterator, unordered_set>		const_iterator;
       typedef __gnu_debug::_Safe_local_iterator<
 	_Base_local_iterator, unordered_set>		local_iterator;
@@ -630,6 +632,8 @@ namespace __debug
       typedef typename _Base::local_iterator	_Base_local_iterator;
 
     public:
+      typedef _Base					normal_type;
+
       typedef typename _Base::size_type			size_type;
       typedef typename _Base::hasher			hasher;
       typedef typename _Base::key_equal			key_equal;
@@ -638,9 +642,9 @@ namespace __debug
       typedef typename _Base::key_type			key_type;
       typedef typename _Base::value_type		value_type;
 
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	_Base_iterator, unordered_multiset>		iterator;
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	_Base_const_iterator, unordered_multiset>	const_iterator;
       typedef __gnu_debug::_Safe_local_iterator<
 	_Base_local_iterator, unordered_multiset>	local_iterator;
diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector
index ced5520..624e4ce 100644
--- a/libstdc++-v3/include/debug/vector
+++ b/libstdc++-v3/include/debug/vector
@@ -128,12 +128,14 @@ namespace __debug
       typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
 
     public:
+      typedef _Base					normal_type;
+
       typedef typename _Base::reference			reference;
       typedef typename _Base::const_reference		const_reference;
 
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	_Base_iterator, vector>				iterator;
-      typedef __gnu_debug::_Safe_iterator<
+      typedef __gnu_debug::_Safe_tagged_iterator<
 	_Base_const_iterator, vector>			const_iterator;
 
       typedef typename _Base::size_type			size_type;
@@ -785,11 +787,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>()(__b); }
     };
 
- template<typename _Iterator, typename _Container, typename _Sequence>
+ template<typename _Iterator, typename _Container, typename _Sequence,
+	  typename _Category>
     _Iterator
-    __niter_base(const __gnu_debug::_Safe_iterator<
+    __niter_base(const __gnu_debug::_Safe_tagged_iterator<
 		 __gnu_cxx::__normal_iterator<_Iterator, _Container>,
-		 _Sequence>& __it)
+		 _Sequence, _Category>& __it)
     { return std::__niter_base(__it.base()); }
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/testsuite/23_containers/list/68222_neg.cc b/libstdc++-v3/testsuite/23_containers/list/68222_neg.cc
new file mode 100644
index 0000000..d969b6a
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/list/68222_neg.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2018 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-do compile { target c++11 } }
+
+#include <list>
+
+void
+test01()
+{
+  // A list of int.
+  const std::list<int> nums = { 1, 2, 3, 4 };
+
+  // Grab the iterator type.
+  using list_itr_type = decltype( std::cbegin( nums ) );
+
+  // Confirm cend returns the same type.
+  static_assert( std::is_same< decltype( std::cend( nums ) ), list_itr_type >::value, "" );
+
+  // The list's iterator type provides a well-formed non-member operator-() with valid return type (long int)
+  using substraction_type
+    = decltype( std::declval<list_itr_type>() - std::declval<list_itr_type>() ); // { dg-error "no match for 'operator-'" }
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/debug_functions.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/debug_functions.cc
index 9fb12ed..1d45e74 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/debug_functions.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/debug_functions.cc
@@ -21,31 +21,6 @@
 #include <unordered_set>
 #include <testsuite_hooks.h>
 
-void test01()
-{
-  using namespace __gnu_debug;
-
-  std::unordered_set<int> u = { 0, 1, 2 };
-  VERIFY( __check_dereferenceable(u.begin()) );
-  auto it = u.begin();
-  VERIFY( __check_dereferenceable(it) );
-
-  VERIFY( __check_dereferenceable(u.cbegin()) );
-  auto cit = u.begin();
-  VERIFY( __check_dereferenceable(cit) );
-
-  VERIFY( !__check_dereferenceable(u.end()) );
-  it = u.end();
-  VERIFY( !__check_dereferenceable(it) );
-
-  auto bucket = u.bucket(0);
-  VERIFY( __check_dereferenceable(u.begin(bucket)) );
-  auto lit = u.begin(bucket);
-  VERIFY( __check_dereferenceable(lit) );
-
-  VERIFY( !__check_dereferenceable(u.end(bucket)) );
-}
-
 void test02()
 {
   using namespace __gnu_debug;
@@ -84,7 +59,6 @@ void test02()
 
 int main()
 {
-  test01();
   test02();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/destructible_debug_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/destructible_debug_neg.cc
index 5127f51..6490414 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/cons/destructible_debug_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/cons/destructible_debug_neg.cc
@@ -45,4 +45,4 @@ test02()
 // { dg-error "value type is destructible" "" { target *-*-* } 0 }
 
 // In Debug Mode the "required from here" errors come from <debug/vector>
-// { dg-error "required from here" "" { target *-*-* } 155 }
+// { dg-error "required from here" "" { target *-*-* } 157 }
diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/debug_functions.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/debug_functions.cc
index ea683ee..acbd0d1 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/debug/debug_functions.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/debug/debug_functions.cc
@@ -20,28 +20,6 @@
 #include <vector>
 #include <testsuite_hooks.h>
 
-void test01()
-{
-  using namespace __gnu_debug;
-
-  std::vector<int> v1(3, 1);
-  VERIFY( __check_dereferenceable(v1.begin()) );
-  std::vector<int>::iterator it = v1.begin();
-  VERIFY( __check_dereferenceable(it) );
-
-  VERIFY( !__check_dereferenceable(v1.end()) );
-  it = v1.end();
-  VERIFY( !__check_dereferenceable(it) );
-
-  const volatile int* pi = 0;
-  VERIFY( !__check_dereferenceable(pi) );
-
-  int i;
-  pi = &i;
-
-  VERIFY( __check_dereferenceable(pi) );
-}
-
 void test02()
 {
   using namespace __gnu_debug;
@@ -67,7 +45,6 @@ void test02()
 
 int main()
 {
-  test01();
   test02();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/util/testsuite_containers.h b/libstdc++-v3/testsuite/util/testsuite_containers.h
index 2dd5a5f..d05d3ac 100644
--- a/libstdc++-v3/testsuite/util/testsuite_containers.h
+++ b/libstdc++-v3/testsuite/util/testsuite_containers.h
@@ -20,6 +20,7 @@
 #ifndef _GLIBCXX_TESTSUITE_CONTAINERS_H
 #define _GLIBCXX_TESTSUITE_CONTAINERS_H
 
+#include <bits/boost_concept_check.h>
 #include <cassert>
 #include <testsuite_container_traits.h>
 #include <utility> // for rel_ops.
@@ -192,6 +193,77 @@ namespace __gnu_test
       forward_members_unordered(_Tp& container) { }
     };
 
+  template<typename _Iterator,
+	   bool _Mutable,
+	   typename = typename std::iterator_traits<_Iterator>::iterator_category>
+    struct iterator_concept_checks;
+
+  template<typename _Iterator>
+    struct iterator_concept_checks<_Iterator, false,
+				   std::forward_iterator_tag>
+    {
+      iterator_concept_checks()
+      {
+	using namespace __gnu_cxx;
+	__function_requires<_ForwardIteratorConcept<_Iterator>>();
+      }
+    };
+
+  template<typename _Iterator>
+    struct iterator_concept_checks<_Iterator, true,
+				   std::forward_iterator_tag>
+    {
+      iterator_concept_checks()
+      {
+	using namespace __gnu_cxx;
+	__function_requires<_Mutable_ForwardIteratorConcept<_Iterator>>();
+      }
+    };
+
+  template<typename _Iterator>
+    struct iterator_concept_checks<_Iterator, false,
+				   std::bidirectional_iterator_tag>
+    {
+      iterator_concept_checks()
+      {
+	using namespace __gnu_cxx;
+	__function_requires<_BidirectionalIteratorConcept<_Iterator>>();
+      }
+    };
+
+  template<typename _Iterator>
+    struct iterator_concept_checks<_Iterator, true,
+				   std::bidirectional_iterator_tag>
+    {
+      iterator_concept_checks()
+      {
+	using namespace __gnu_cxx;
+	__function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator>>();
+      }
+    };
+
+  template<typename _Iterator>
+    struct iterator_concept_checks<_Iterator, false,
+				   std::random_access_iterator_tag>
+    {
+      iterator_concept_checks()
+      {
+	using namespace __gnu_cxx;
+	__function_requires<_RandomAccessIteratorConcept<_Iterator>>();
+      }
+    };
+
+  template<typename _Iterator>
+    struct iterator_concept_checks<_Iterator, true,
+				   std::random_access_iterator_tag>
+    {
+      iterator_concept_checks()
+      {
+	using namespace __gnu_cxx;
+	__function_requires<_Mutable_RandomAccessIteratorConcept<_Iterator>>();
+      }
+    };
+
   template<typename _Tp>
     struct citerator
     {
@@ -210,6 +282,11 @@ namespace __gnu_test
 	  // when comparing iterators.
 	  using namespace std::rel_ops;
 
+	  iterator_concept_checks<typename _Tp::iterator,
+				  !(traits_type::is_associative::value
+				    || traits_type::is_unordered::value)> cc;
+	  iterator_concept_checks<typename _Tp::const_iterator, false> ccc;
+
 	  assert( _S_container.cbegin() == _S_container.begin() );
 	  assert( _S_container.end() == _S_container.cend() );
 	  assert( _S_container.cbegin() != _S_container.cend() );

[-- Attachment #3: ChangeLog.entry --]
[-- Type: text/plain, Size: 7622 bytes --]

2018-08-03  François Dumont  <fdumont@gcc.gnu.org>

	* include/debug/safe_iterator.h
	(_Safe_tagged_iterator<_It, _Sq, _Cat =
	typename std::iterator_traits<_It>::iterator_category>): New.
	(_Safe_iterator<_It, _Sq>::operator++()): Move...
	(_Safe_tagged_iterator<_It, _Sq, std::forward_iterator_tag>
	::operator++()): ...here.
	(_Safe_iterator<_It, _Sq>::operator++(int)): Move...
	(_Safe_tagged_iterator<_It, _Sq, std::forward_iterator_tag>
	::operator++(int)): ...here.
	(_Safe_iterator<_It, _Sq>::operator--()): Move...
	(_Safe_tagged_iterator<_It, _Sq, std::bidirectional_iterator_tag>
	::operator--()): ...here.
	(_Safe_iterator<_It, _Sq>::operator--(int)): Move...
	(_Safe_tagged_iterator<_It, _Sq, std::bidirectional_iterator_tag>
	::operator--(int)): ...here.
	(_Safe_iterator<_It, _Sq>::operator[](const difference_type&)): Move...
	(_Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator[](const difference_type&)): ...here.
	(_Safe_iterator<_It, _Sq>::operator+=(const difference_type&)): Move...
	(_Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator+=(const difference_type&)): ...here.
	(_Safe_iterator<_It, _Sq>::operator+(const difference_type&)): Move...
	(_Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator+(const difference_type&)): ...here.
	(_Safe_iterator<_It, _Sq>::operator-=(const difference_type&)): Move...
	(_Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator-=(const difference_type&)): ...here.
	(_Safe_iterator<_It, _Sq>::operator-(const difference_type&)): Move...
	(_Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator-(const difference_type&)): ...here.
	(operator==(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace
	with...
	(operator==(const _Safe_tagged_iterator<>&,
	const _Safe_tagged_iterator<>&): ...that.
	(operator==(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace
	with...
	(operator==(const _Safe_tagged_iterator<>&,
	const _Safe_tagged_iterator<>&): ...that.
	(operator!=(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace
	with...
	(operator!=(const _Safe_tagged_iterator<>&,
	const _Safe_tagged_iterator<>&): ...that.
	(operator<(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace
	with...
	(operator<(const _Safe_tagged_iterator<_It, _Sq,
		std::random_access_iterator_tag>&,
		const _Safe_tagged_iterator<_It, _Sq,
		std::random_access_iterator_tag>&)): ...that.
	(operator<=(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace
	with...
	(operator<=(const _Safe_tagged_iterator<_It, _Sq,
		std::random_access_iterator_tag>&,
		const _Safe_tagged_iterator<_It, _Sq,
		std::random_access_iterator_tag>&)): ...that.
	(operator>(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace
	with...
	(operator>(const _Safe_tagged_iterator<_It, _Sq,
		std::random_access_iterator_tag>&,
		const _Safe_tagged_iterator<_It, _Sq,
		std::random_access_iterator_tag>&)): ...that.
	(operator>=(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace
	with...
	(operator>=(const _Safe_tagged_iterator<_It, _Sq,
		std::random_access_iterator_tag>&,
		const _Safe_tagged_iterator<_It, _Sq,
		std::random_access_iterator_tag>&)): ...that.
	(operator-(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace
	with...
	(operator-(const _Safe_tagged_iterator<_It, _Sq,
		std::random_access_iterator_tag>&,
		const _Safe_tagged_iterator<_It, _Sq,
		std::random_access_iterator_tag>&)): ...that.
	(operator+(const difference_type&, const _Safe_iterator<>&)): Replace
	with...
	(operator+(const difference_type&,
		const _Safe_tagged_iterator<_It, _Sq,
	std::random_access_iterator_tag>&)): ...that.
	* include/debug/deque
	(std::__debug::deque<>::normal_type): New typedef.
	(std::__debug::deque<>::iterator): Use _Safe_tagged_iterator.
	(std::__debug::deque<>::const_iterator): Likewise.
	* include/debug/forward_list
	(std::__debug::forward_list<>::normal_type): New typedef.
	(std::__debug::forward_list<>::iterator): Use _Safe_tagged_iterator.
	(std::__debug::forward_list<>::const_iterator): Likewise.
	* include/debug/list
	(std::__debug::list<>::normal_type): New typedef.
	(std::__debug::list<>::iterator): Use _Safe_tagged_iterator.
	(std::__debug::list<>::const_iterator): Likewise.
	* include/debug/map.h
	(std::__debug::map<>::normal_type): New typedef.
	(std::__debug::map<>::iterator): Use _Safe_tagged_iterator.
	(std::__debug::map<>::const_iterator): Likewise.
	* include/debug/multimap.h
	(std::__debug::multimap<>::normal_type): New typedef.
	(std::__debug::multimap<>::iterator): Use _Safe_tagged_iterator.
	(std::__debug::multimap<>::const_iterator): Likewise.
	* include/debug/set.h
	(std::__debug::set<>::normal_type): New typedef.
	(std::__debug::set<>::iterator): Use _Safe_tagged_iterator.
	(std::__debug::set<>::const_iterator): Likewise.
	* include/debug/multiset.h
	(std::__debug::multiset<>::normal_type): New typedef.
	(std::__debug::multiset<>::iterator): Use _Safe_tagged_iterator.
	(std::__debug::multiset<>::const_iterator): Likewise.
	* include/debug/string
	(std::__debug::basic_string<>::normal_type): New typedef.
	(std::__debug::basic_string<>::iterator): Use _Safe_tagged_iterator.
	(std::__debug::basic_string<>::const_iterator): Likewise.
	* include/debug/unordered_map
	(std::__debug::unordered_map<>::normal_type): New typedef.
	(std::__debug::unordered_map<>::iterator): Use _Safe_tagged_iterator.
	(std::__debug::unordered_map<>::const_iterator): Likewise.
	(std::__debug::unordered_multimap<>::normal_type): New typedef.
	(std::__debug::unordered_multimap<>::iterator): Use _Safe_tagged_iterator.
	(std::__debug::unordered_multimap<>::const_iterator): Likewise.
	* include/debug/unordered_set
	(std::__debug::unordered_set<>::normal_type): New typedef.
	(std::__debug::unordered_set<>::iterator): Use _Safe_tagged_iterator.
	(std::__debug::unordered_set<>::const_iterator): Likewise.
	(std::__debug::unordered_multiset<>::normal_type): New typedef.
	(std::__debug::unordered_multiset<>::iterator): Use _Safe_tagged_iterator.
	(std::__debug::unordered_multiset<>::const_iterator): Likewise.
	* include/debug/formatter.h: Adapt.
	* include/debug/helper_functions.h
	(__get_distance<>(const _Safe_tagged_iterator<>&,
	const _Safe_tagged_iterator<>&)): New definition.
	(__get_distance<>(const _Safe_local_iterator<>&,
	const _Safe_local_iterator<>&)): Likewise.
	(__valid_range(const _Safe_tagged_iterator<>&,
	const _Safe_tagged_iterator<>&, typename _Distance_traits<>::__type&):
	Likewise.
	(__valid_range(const _Safe_local_iterator<>&,
	const _Safe_local_iterator<>&, typename _Distance_traits<>::__type&):
	Likewise.
	(__can_advance): Adapt.
	(__is_safe_random_iterator<>): Remove.
	* include/debug/functions.h: Include <bits/stl_iterator.h>.
	(__check_dereferenceable): Delete.
	(__foreign_iterator_aux4, __foreign_iterator_aux3): Adapt.
	(__foreign_iterator_aux2, __foreign_iterator_aux): Adapt.
	(__foreign_iterator): Adapt.
	* include/debug/stl_iterator.h
	(__is_safe_random_iterator<std::reverse_iterator<>>): Remove.
	(__base(const std::reverse_iterator<_Safe_tagged_iterator<_It, _Sq,
	std::random_access_iterator_tag>)): New overload.
	(__niter_base): Adapt.
	* testsuite/util/testsuite_containers.h:
	Include <bits/boost_concept_check.h>.
	(iterator_concept_checks<_It, _Mutable, _Category>): New.
	(citerator<_Cont>::forward_members::forward_members()): Instantiate
	latter for container iterator and const_iterator.
	* testsuite/23_containers/list/68222_neg.cc: New.
	* testsuite/23_containers/vector/cons/destructible_debug_neg.cc: Adapt
	line number.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-08-23 15:23 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-02 20:16 PR libstdc++/68222 Hide safe iterator operators François Dumont
2018-08-07 13:47 ` Jonathan Wakely
2018-08-07 22:41   ` Jonathan Wakely
2018-08-18 20:31     ` François Dumont
2018-08-21  9:33       ` Jonathan Wakely
2018-08-21 20:18         ` François Dumont
     [not found]           ` <20180823075136.GR4149@redhat.com>
     [not found]             ` <20180823142956.GV4149@redhat.com>
2018-08-23 15:23               ` Jonathan Wakely
2018-08-07 22:39 ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).