Hi

Following this previous patch https://gcc.gnu.org/pipermail/libstdc++/2024-August/059418.html I've completed it for the _Safe_unordered_container_base type and implemented the rest of the change to store the safe iterator sequence as a pointer-to-const.

    libstdc++: Make debug iterator pointer sequence const [PR116369]

    In revision a35dd276cbf6236e08bcf6e56e62c2be41cf6e3c the debug sequence
    have been made mutable to allow attach iterators to const containers.
    This change completes this fix by also declaring debug unordered container
    members mutable.

    Additionally the debug iterator sequence is now a pointer-to-const and so     _Safe_sequence_base _M_attach and all other methods are const qualified.
    Symbols export are maintained thanks to __asm directives.

    libstdc++-v3/ChangeLog:

            PR c++/116369
            * include/debug/safe_base.h
            (_Safe_iterator_base::_M_sequence): Declare as pointer-to-const.             (_Safe_iterator_base::_M_attach, _M_attach_single): Take pointer-to-const             _Safe_sequence_base. Add __asm directive to preserve name mangling.             (_Safe_sequence_base::_M_detach_all, _M_detach_singular, _M_revalidate_singular)             (_M_swap, _M_get_mutex, _M_attach, _M_attach_single, _M_detash, _M_detash_single):             Add const qualifier and __asm directive to preserve name mangling.
            * include/debug/safe_unordered_base.h
            (_Safe_local_iterator_base::_M_get_container): Make public and return
            _Safe_unordered_container_base as pointer-to-const.
(_Safe_local_iterator_base::_Safe_local_iterator_base): Take
            _Safe_unordered_container_base as pointer-to-const.
            (_Safe_unordered_container_base::_M_attach, _M_attach_single): Take             _Safe_unordered_container_base as pointer-to-const. Add __asm directive to preserve
            name mangling.
            (_Safe_unordered_container_base::_M_local_iterators, _M_const_local_iterators):
            Add mutable.
            (_Safe_unordered_container_base::_M_detach_all, _M_swap, _M_attach_local)             (_M_attach_local_single, _M_detach_loca, _M_detach_local_single): Add const
            qualifier and __asm directive to preserve name mangling.
            * include/debug/safe_iterator.h (_Safe_iterator<>::_M_attach, _M_attach_single):
            Take _Safe_sequence_base as pointer-to-const.
            (_Safe_iterator<>::_M_get_sequence): Add const_cast and comment about it.             * include/debug/safe_local_iterator.h (_Safe_local_iterator<>): Replace usages
            of _M_sequence member by _M_get_container().
            (_Safe_local_iterator<>::_M_attach, _M_attach_single): Take
            _Safe_unordered_container_base as pointer-to-const.
            (_Safe_local_iterator<>::_M_get_sequence): Rename into...
            (_Safe_local_iterator<>::_M_get_ucontainer): ...this. Add necessary const_cast and
            comment to explain it.
            * include/debug/safe_sequence.h
            (_Safe_sequence<>::_M_invalidate_if, _M_transfer_from_if): Add const qualifier.
            * include/debug/safe_sequence.tcc: Adapt.
            * src/c++11/debug.cc: Adapt to const qualification.
            * testsuite/util/testsuite_containers.h
(forward_members_unordered::forward_members_unordered): Add check on local_iterator
            conversion to const_local_iterator.
            (forward_members::forward_members): Add check on iterator conversion to
            const_iterator.

Also available as a PR

https://forge.sourceware.org/gcc/gcc-TEST/pulls/47

Tested under Linux x64.

Ok to commit ?

François
diff --git a/libstdc++-v3/include/debug/safe_base.h 
b/libstdc++-v3/include/debug/safe_base.h
index cf3f1708ad2..99638ca48f9 100644
--- a/libstdc++-v3/include/debug/safe_base.h
+++ b/libstdc++-v3/include/debug/safe_base.h
@@ -53,8 +53,10 @@ namespace __gnu_debug
 
   public:
     /** The sequence this iterator references; may be NULL to indicate
-       a singular iterator. */
-    _Safe_sequence_base*       _M_sequence;
+     *  a singular iterator. Stored as pointer-to-const because sequence
+     *  could be declared as const.
+     */
+    const _Safe_sequence_base* _M_sequence;
 
     /** The version number of this iterator. The sentinel value 0 is
      *  used to indicate an invalidated iterator (i.e., one that is
@@ -92,7 +94,7 @@ namespace __gnu_debug
     : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
     {
       if (!std::__is_constant_evaluated())
-       this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant);
+       this->_M_attach(__seq, __constant);
     }
 
     /** Initializes the iterator to reference the same sequence that
@@ -123,11 +125,15 @@ namespace __gnu_debug
      * unattached.
      */
     void
-    _M_attach(_Safe_sequence_base* __seq, bool __constant);
+    _M_attach(const _Safe_sequence_base* __seq, bool __constant)
+      __asm("_ZN11__gnu_debug19_Safe_iterator_base9"
+           "_M_attachEPNS_19_Safe_sequence_baseEb");
 
     /** Likewise, but not thread-safe. */
     void
-    _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ();
+    _M_attach_single(const _Safe_sequence_base* __seq, bool __constant) throw 
()
+      __asm("_ZN11__gnu_debug19_Safe_iterator_base16"
+           "_M_attach_singleEPNS_19_Safe_sequence_baseEb");
 
     /** Detach the iterator for whatever sequence it is attached to,
      * if any.
@@ -246,14 +252,16 @@ namespace __gnu_debug
 
     /** Detach all iterators, leaving them singular. */
     void
-    _M_detach_all();
+    _M_detach_all() const
+      __asm("_ZN11__gnu_debug19_Safe_sequence_base13_M_detach_allEv");
 
     /** Detach all singular iterators.
      *  @post for all iterators i attached to this sequence,
      *   i->_M_version == _M_version.
      */
     void
-    _M_detach_singular();
+    _M_detach_singular() const
+      __asm("_ZN11__gnu_debug19_Safe_sequence_base18_M_detach_singularEv");
 
     /** Revalidates all attached singular iterators.  This method may
      *  be used to validate iterators that were invalidated before
@@ -261,7 +269,8 @@ namespace __gnu_debug
      *  valid again).
      */
     void
-    _M_revalidate_singular();
+    _M_revalidate_singular() const
+      __asm("_ZN11__gnu_debug19_Safe_sequence_base22_M_revalidate_singularEv");
 
     /** Swap this sequence with the given sequence. This operation
      *  also swaps ownership of the iterators, so that when the
@@ -269,11 +278,13 @@ namespace __gnu_debug
      *  one container now reference the other container.
      */
     void
-    _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT;
+    _M_swap(const _Safe_sequence_base& __x) const _GLIBCXX_USE_NOEXCEPT
+      __asm("_ZN11__gnu_debug19_Safe_sequence_base7_M_swapERS0_");
 
     /** For use in _Safe_sequence. */
     __gnu_cxx::__mutex&
-    _M_get_mutex() throw ();
+    _M_get_mutex() const throw ()
+      __asm("_ZN11__gnu_debug19_Safe_sequence_base12_M_get_mutexEv");
 
     /** Invalidates all iterators. */
     void
@@ -283,19 +294,19 @@ namespace __gnu_debug
   private:
     /** Attach an iterator to this sequence. */
     void
-    _M_attach(_Safe_iterator_base* __it, bool __constant);
+    _M_attach(_Safe_iterator_base* __it, bool __constant) const;
 
     /** Likewise but not thread safe. */
     void
-    _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw ();
+    _M_attach_single(_Safe_iterator_base* __it, bool __constant) const throw 
();
 
     /** Detach an iterator from this sequence */
     void
-    _M_detach(_Safe_iterator_base* __it);
+    _M_detach(_Safe_iterator_base* __it) const;
 
     /** Likewise but not thread safe. */
     void
-    _M_detach_single(_Safe_iterator_base* __it) throw ();
+    _M_detach_single(_Safe_iterator_base* __it) const throw ();
   };
 } // namespace __gnu_debug
 
diff --git a/libstdc++-v3/include/debug/safe_iterator.h 
b/libstdc++-v3/include/debug/safe_iterator.h
index 7c563381d0b..e0b1b46939c 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -224,7 +224,7 @@ namespace __gnu_debug
                              _M_message(__msg_init_copy_singular)
                              ._M_iterator(*this, "this")
                              ._M_iterator(__x, "other"));
-       _Safe_sequence_base* __seq = __x._M_sequence;
+       const _Safe_sequence_base* __seq = __x._M_sequence;
        __x._M_detach();
        std::swap(base(), __x.base());
        _M_attach(__seq);
@@ -445,12 +445,12 @@ namespace __gnu_debug
 
       /** Attach iterator to the given sequence. */
       void
-      _M_attach(_Safe_sequence_base* __seq)
+      _M_attach(const _Safe_sequence_base* __seq)
       { _Safe_base::_M_attach(__seq, _S_constant()); }
 
       /** Likewise, but not thread-safe. */
       void
-      _M_attach_single(_Safe_sequence_base* __seq)
+      _M_attach_single(const _Safe_sequence_base* __seq)
       { _Safe_base::_M_attach_single(__seq, _S_constant()); }
 
       /// Is the iterator dereferenceable?
@@ -500,7 +500,13 @@ namespace __gnu_debug
       typename __gnu_cxx::__conditional_type<
        _IsConstant::__value, const _Sequence*, _Sequence*>::__type
       _M_get_sequence() const
-      { return static_cast<_Sequence*>(_M_sequence); }
+      {
+       // Looks like not const-correct, but if _IsConstant the constness
+       // is restored when returning the sequence pointer and if not
+       // _IsConstant we are allowed to remove constness.
+       return static_cast<_Sequence*>
+         (const_cast<_Safe_sequence_base*>(_M_sequence));
+      }
 
       // Get distance to __rhs.
       typename _Distance_traits<_Iterator>::__type
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h 
b/libstdc++-v3/include/debug/safe_local_iterator.h
index c84f4f10093..9e32985d9f5 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.h
+++ b/libstdc++-v3/include/debug/safe_local_iterator.h
@@ -52,15 +52,14 @@ namespace __gnu_debug
   /** \brief Safe iterator wrapper.
    *
    *  The class template %_Safe_local_iterator is a wrapper around an
-   *  iterator that tracks the iterator's movement among sequences and
-   *  checks that operations performed on the "safe" iterator are
-   *  legal. In additional to the basic iterator operations (which are
-   *  validated, and then passed to the underlying iterator),
-   *  %_Safe_local_iterator has member functions for iterator invalidation,
-   *  attaching/detaching the iterator from sequences, and querying
-   *  the iterator's state.
+   *  iterator that tracks the iterator's movement among unordered containers
+   *  and checks that operations performed on the "safe" iterator are legal.
+   *  In additional to the basic iterator operations (which are validated,
+   *  and then passed to the underlying iterator), %_Safe_local_iterator has
+   *  member functions for iterator invalidation, attaching/detaching the
+   *  iterator from unordered containers, and querying the iterator's state.
    */
-  template<typename _Iterator, typename _Sequence>
+  template<typename _Iterator, typename _UContainer>
     class _Safe_local_iterator
     : private _Iterator
     , public _Safe_local_iterator_base
@@ -68,28 +67,28 @@ namespace __gnu_debug
       typedef _Iterator _Iter_base;
       typedef _Safe_local_iterator_base _Safe_base;
 
-      typedef typename _Sequence::size_type size_type;
+      typedef typename _UContainer::size_type size_type;
 
       typedef std::iterator_traits<_Iterator> _Traits;
 
       typedef std::__are_same<
-       typename _Sequence::_Base::const_local_iterator,
+       typename _UContainer::_Base::const_local_iterator,
        _Iterator> _IsConstant;
 
       typedef typename __gnu_cxx::__conditional_type<_IsConstant::__value,
-       typename _Sequence::_Base::local_iterator,
-       typename _Sequence::_Base::const_local_iterator>::__type
+       typename _UContainer::_Base::local_iterator,
+       typename _UContainer::_Base::const_local_iterator>::__type
       _OtherIterator;
 
       typedef _Safe_local_iterator _Self;
-      typedef _Safe_local_iterator<_OtherIterator, _Sequence> _OtherSelf;
+      typedef _Safe_local_iterator<_OtherIterator, _UContainer> _OtherSelf;
 
       struct _Unchecked { };
 
       _Safe_local_iterator(const _Safe_local_iterator& __x,
                           _Unchecked) noexcept
       : _Iter_base(__x.base())
-      { _M_attach(__x._M_sequence); }
+      { _M_attach(__x._M_get_container()); }
 
     public:
       typedef _Iterator                                        iterator_type;
@@ -104,12 +103,13 @@ namespace __gnu_debug
 
       /**
        * @brief Safe iterator construction from an unsafe iterator and
-       * its sequence.
+       * its unordered container.
        *
-       * @pre @p seq is not NULL
+       * @pre @p cont is not NULL
        * @post this is not singular
        */
-      _Safe_local_iterator(_Iterator __i, const _Safe_sequence_base* __cont)
+      _Safe_local_iterator(_Iterator __i,
+                          const _Safe_unordered_container_base* __cont)
       : _Iter_base(__i), _Safe_base(__cont, _S_constant())
       { }
 
@@ -126,7 +126,7 @@ namespace __gnu_debug
                              _M_message(__msg_init_copy_singular)
                              ._M_iterator(*this, "this")
                              ._M_iterator(__x, "other"));
-       _M_attach(__x._M_sequence);
+       _M_attach(__x._M_get_container());
       }
 
       /**
@@ -141,7 +141,7 @@ namespace __gnu_debug
                              _M_message(__msg_init_copy_singular)
                              ._M_iterator(*this, "this")
                              ._M_iterator(__x, "other"));
-       auto __cont = __x._M_sequence;
+       auto __cont = __x._M_get_container();
        __x._M_detach();
        std::swap(base(), __x.base());
        _M_attach(__cont);
@@ -156,7 +156,7 @@ namespace __gnu_debug
          const _Safe_local_iterator<_MutableIterator,
          typename __gnu_cxx::__enable_if<_IsConstant::__value &&
            std::__are_same<_MutableIterator, _OtherIterator>::__value,
-                                         _Sequence>::__type>& __x) noexcept
+                                         _UContainer>::__type>& __x) noexcept
        : _Iter_base(__x.base())
        {
          // _GLIBCXX_RESOLVE_LIB_DEFECTS
@@ -166,7 +166,7 @@ namespace __gnu_debug
                                _M_message(__msg_init_const_singular)
                                ._M_iterator(*this, "this")
                                ._M_iterator(__x, "other"));
-         _M_attach(__x._M_sequence);
+         _M_attach(__x._M_get_container());
        }
 
       /**
@@ -193,7 +193,7 @@ namespace __gnu_debug
          {
            _M_detach();
            base() = __x.base();
-           _M_attach(__x._M_sequence);
+           _M_attach(__x._M_get_container());
          }
 
        return *this;
@@ -225,7 +225,7 @@ namespace __gnu_debug
          {
            _M_detach();
            base() = __x.base();
-           _M_attach(__x._M_sequence);
+           _M_attach(__x._M_get_container());
          }
 
        __x._M_detach();
@@ -318,15 +318,15 @@ namespace __gnu_debug
        */
       operator _Iterator() const { return *this; }
 
-      /** Attach iterator to the given sequence. */
+      /** Attach iterator to the given unordered container. */
       void
-      _M_attach(_Safe_sequence_base* __seq)
-      { _Safe_base::_M_attach(__seq, _S_constant()); }
+      _M_attach(const _Safe_unordered_container_base* __cont)
+      { _Safe_base::_M_attach(__cont, _S_constant()); }
 
       /** Likewise, but not thread-safe. */
       void
-      _M_attach_single(_Safe_sequence_base* __seq)
-      { _Safe_base::_M_attach_single(__seq, _S_constant()); }
+      _M_attach_single(const _Safe_unordered_container_base* __cont)
+      { _Safe_base::_M_attach_single(__cont, _S_constant()); }
 
       /// Is the iterator dereferenceable?
       bool
@@ -353,25 +353,31 @@ namespace __gnu_debug
       typename _Distance_traits<_Iterator>::__type
       _M_get_distance_to(const _Safe_local_iterator& __rhs) const;
 
-      // The sequence this iterator references.
+      // The unordered container this iterator references.
       typename __gnu_cxx::__conditional_type<
-       _IsConstant::__value, const _Sequence*, _Sequence*>::__type
-      _M_get_sequence() const
-      { return static_cast<_Sequence*>(_M_sequence); }
+       _IsConstant::__value, const _UContainer*, _UContainer*>::__type
+      _M_get_ucontainer() const
+      {
+       // Looks like not const-correct, but if _IsConstant the constness
+       // is restored when returning the container pointer and if not
+       // _IsConstant we are allowed to remove constness.
+       return static_cast<_UContainer*>
+         (const_cast<_Safe_unordered_container_base*>(_M_get_container()));
+      }
 
-      /// Is this iterator equal to the sequence's begin(bucket) iterator?
+      /// Is this iterator equal to the container's begin(bucket) iterator?
       bool _M_is_begin() const
-      { return base() == _M_get_sequence()->_M_base().begin(bucket()); }
+      { return base() == _M_get_ucontainer()->_M_base().begin(bucket()); }
 
-      /// Is this iterator equal to the sequence's end(bucket) iterator?
+      /// Is this iterator equal to the container's end(bucket) iterator?
       bool _M_is_end() const
-      { return base() == _M_get_sequence()->_M_base().end(bucket()); }
+      { return base() == _M_get_ucontainer()->_M_base().end(bucket()); }
 
       /// Is this iterator part of the same bucket as the other one?
       template<typename _Other>
        bool
        _M_in_same_bucket(const _Safe_local_iterator<_Other,
-                                                    _Sequence>& __other) const
+                                                    _UContainer>& __other) 
const
        { return bucket() == __other.bucket(); }
 
       friend inline bool
@@ -404,31 +410,31 @@ namespace __gnu_debug
     };
 
   /** Safe local iterators know how to check if they form a valid range. */
-  template<typename _Iterator, typename _Sequence>
+  template<typename _Iterator, typename _UContainer>
     inline bool
-    __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
-                 const _Safe_local_iterator<_Iterator, _Sequence>& __last,
+    __valid_range(const _Safe_local_iterator<_Iterator, _UContainer>& __first,
+                 const _Safe_local_iterator<_Iterator, _UContainer>& __last,
                  typename _Distance_traits<_Iterator>::__type& __dist_info)
     { return __first._M_valid_range(__last, __dist_info); }
 
-  template<typename _Iterator, typename _Sequence>
+  template<typename _Iterator, typename _UContainer>
     inline bool
-    __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
-                 const _Safe_local_iterator<_Iterator, _Sequence>& __last)
+    __valid_range(const _Safe_local_iterator<_Iterator, _UContainer>& __first,
+                 const _Safe_local_iterator<_Iterator, _UContainer>& __last)
     {
       typename _Distance_traits<_Iterator>::__type __dist_info;
       return __first._M_valid_range(__last, __dist_info);
     }
 
 #if __cplusplus < 201103L
-  template<typename _Iterator, typename _Sequence>
-    struct _Unsafe_type<_Safe_local_iterator<_Iterator, _Sequence> >
+  template<typename _Iterator, typename _UContainer>
+    struct _Unsafe_type<_Safe_local_iterator<_Iterator, _UContainer> >
     { typedef _Iterator _Type; };
 #endif
 
-  template<typename _Iterator, typename _Sequence>
+  template<typename _Iterator, typename _UContainer>
     inline _Iterator
-    __unsafe(const _Safe_local_iterator<_Iterator, _Sequence>& __it)
+    __unsafe(const _Safe_local_iterator<_Iterator, _UContainer>& __it)
     { return __it.base(); }
 
 } // namespace __gnu_debug
diff --git a/libstdc++-v3/include/debug/safe_sequence.h 
b/libstdc++-v3/include/debug/safe_sequence.h
index 6b35afa66c6..599f770554b 100644
--- a/libstdc++-v3/include/debug/safe_sequence.h
+++ b/libstdc++-v3/include/debug/safe_sequence.h
@@ -114,7 +114,7 @@ namespace __gnu_debug
          in the safe ones. */
       template<typename _Predicate>
        void
-       _M_invalidate_if(_Predicate __pred);
+       _M_invalidate_if(_Predicate __pred) const;
 
       /** Transfers all iterators @c x that reference @c from sequence,
          are not singular, and for which @c __pred(x) returns @c
@@ -122,7 +122,7 @@ namespace __gnu_debug
          in the safe ones. */
       template<typename _Predicate>
        void
-       _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred);
+       _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred) const;
     };
 
   /// Like _Safe_sequence but with a special _M_invalidate_all implementation
@@ -133,12 +133,12 @@ namespace __gnu_debug
     {
     protected:
       void
-      _M_invalidate_all()
+      _M_invalidate_all() const
       {
        typedef typename _Sequence::const_iterator _Const_iterator;
        typedef typename _Const_iterator::iterator_type _Base_const_iterator;
        typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
-       const _Sequence& __seq = *static_cast<_Sequence*>(this);
+       const _Sequence& __seq = *static_cast<const _Sequence*>(this);
        this->_M_invalidate_if(_Not_equal(__seq._M_base().end()));
       }
     };
diff --git a/libstdc++-v3/include/debug/safe_sequence.tcc 
b/libstdc++-v3/include/debug/safe_sequence.tcc
index 336bf2a0b2b..62872b1d788 100644
--- a/libstdc++-v3/include/debug/safe_sequence.tcc
+++ b/libstdc++-v3/include/debug/safe_sequence.tcc
@@ -35,7 +35,7 @@ namespace __gnu_debug
     template<typename _Predicate>
       void
       _Safe_sequence<_Sequence>::
-      _M_invalidate_if(_Predicate __pred)
+      _M_invalidate_if(_Predicate __pred) const
       {
        typedef typename _Sequence::iterator iterator;
        typedef typename _Sequence::const_iterator const_iterator;
@@ -66,7 +66,7 @@ namespace __gnu_debug
     template<typename _Predicate>
       void
       _Safe_sequence<_Sequence>::
-      _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred)
+      _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred) const
       {
        if (this == std::__addressof(__from))
          return;
@@ -104,7 +104,7 @@ namespace __gnu_debug
            }
 
          for (_Safe_iterator_base* __iter2 = __from._M_const_iterators;
-                __iter2;)
+              __iter2;)
            {
              _Safe_iterator_base* __victim_base = __iter2;
              const_iterator* __victim =
diff --git a/libstdc++-v3/include/debug/safe_unordered_base.h 
b/libstdc++-v3/include/debug/safe_unordered_base.h
index 1547f5b7b9d..4d0bf6cd156 100644
--- a/libstdc++-v3/include/debug/safe_unordered_base.h
+++ b/libstdc++-v3/include/debug/safe_unordered_base.h
@@ -49,6 +49,10 @@ namespace __gnu_debug
    */
   class _Safe_local_iterator_base : public _Safe_iterator_base
   {
+  public:
+    const _Safe_unordered_container_base*
+    _M_get_container() const noexcept;
+
   protected:
     /** Initializes the iterator and makes it singular. */
     _Safe_local_iterator_base()
@@ -61,32 +65,36 @@ namespace __gnu_debug
      *  singular. Otherwise, the iterator will reference @p __seq and
      *  be nonsingular.
      */
-    _Safe_local_iterator_base(const _Safe_sequence_base* __seq, bool 
__constant)
-    { this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); }
+    _Safe_local_iterator_base(const _Safe_unordered_container_base* __seq,
+                             bool __constant)
+    { _M_attach(__seq, __constant); }
 
     /** Initializes the iterator to reference the same container that
        @p __x does. @p __constant is true if this is a constant
        iterator, and false if it is mutable. */
     _Safe_local_iterator_base(const _Safe_local_iterator_base& __x,
                              bool __constant)
-    { this->_M_attach(__x._M_sequence, __constant); }
+    { this->_M_attach(__x._M_get_container(), __constant); }
 
     ~_Safe_local_iterator_base() { this->_M_detach(); }
 
-    _Safe_unordered_container_base*
-    _M_get_container() const noexcept;
-
     /** Attaches this iterator to the given container, detaching it
      * from whatever container it was attached to originally. If the
      * new container is the NULL pointer, the iterator is left
      * unattached.
      */
     void
-    _M_attach(_Safe_sequence_base* __seq, bool __constant);
+    _M_attach(const _Safe_unordered_container_base* __seq,
+             bool __constant)
+      __asm("_ZN11__gnu_debug25_Safe_local_iterator_base9"
+           "_M_attachEPNS_19_Safe_sequence_baseEb");
 
     /** Likewise, but not thread-safe. */
     void
-    _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ();
+    _M_attach_single(const _Safe_unordered_container_base* __seq,
+                    bool __constant) noexcept
+      __asm("_ZN11__gnu_debug25_Safe_local_iterator_base16"
+           "_M_attach_singleEPNS_19_Safe_sequence_baseEb");
 
     /** Detach the iterator for whatever container it is attached to,
      * if any.
@@ -124,10 +132,10 @@ namespace __gnu_debug
 
   public:
     /// The list of mutable local iterators that reference this container
-    _Safe_iterator_base* _M_local_iterators;
+    mutable _Safe_iterator_base* _M_local_iterators;
 
     /// The list of constant local iterators that reference this container
-    _Safe_iterator_base* _M_const_local_iterators;
+    mutable _Safe_iterator_base* _M_const_local_iterators;
 
   protected:
     // Initialize with a version number of 1 and no iterators
@@ -153,7 +161,8 @@ namespace __gnu_debug
 
     /** Detach all iterators, leaving them singular. */
     void
-    _M_detach_all();
+    _M_detach_all() const
+      
__asm("_ZN11__gnu_debug30_Safe_unordered_container_base13_M_detach_allEv");
 
     /** Swap this container with the given container. This operation
      *  also swaps ownership of the iterators, so that when the
@@ -161,25 +170,32 @@ namespace __gnu_debug
      *  one container now reference the other container.
      */
     void
-    _M_swap(_Safe_unordered_container_base& __x) noexcept;
+    _M_swap(const _Safe_unordered_container_base& __x) const noexcept
+      __asm("_ZN11__gnu_debug30_Safe_unordered_container_base7_M_swapERS0_");
 
   private:
     /** Attach an iterator to this container. */
     void
-    _M_attach_local(_Safe_iterator_base* __it, bool __constant);
+    _M_attach_local(_Safe_iterator_base* __it, bool __constant) const;
 
     /** Likewise but not thread safe. */
     void
-    _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw 
();
+    _M_attach_local_single(_Safe_iterator_base* __it,
+                          bool __constant) const noexcept;
 
     /** Detach an iterator from this container */
     void
-    _M_detach_local(_Safe_iterator_base* __it);
+    _M_detach_local(_Safe_iterator_base* __it) const;
 
     /** Likewise but not thread safe. */
     void
-    _M_detach_local_single(_Safe_iterator_base* __it) throw ();
+    _M_detach_local_single(_Safe_iterator_base* __it) const noexcept;
   };
+
+  inline const _Safe_unordered_container_base*
+  _Safe_local_iterator_base::
+  _M_get_container() const noexcept
+  { return static_cast<const _Safe_unordered_container_base*>(_M_sequence); }
 } // namespace __gnu_debug
 
 #endif
diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc
index 3533b5e1df1..aa56e451861 100644
--- a/libstdc++-v3/src/c++11/debug.cc
+++ b/libstdc++-v3/src/c++11/debug.cc
@@ -54,7 +54,7 @@ namespace
    *  in order to limit contention without breaking current library binary
    *  compatibility. */
   __gnu_cxx::__mutex&
-  get_safe_base_mutex(void* address)
+  get_safe_base_mutex(const void* address)
   {
     // Use arbitrarily __gnu_debug::vector<int> as the container giving
     // alignment of debug containers.
@@ -70,9 +70,9 @@ namespace
 #pragma GCC diagnostic warning "-Wabi=6"
 
   void
-  swap_its(__gnu_debug::_Safe_sequence_base& __lhs,
+  swap_its(const __gnu_debug::_Safe_sequence_base& __lhs,
           __gnu_debug::_Safe_iterator_base*& __lhs_its,
-          __gnu_debug::_Safe_sequence_base& __rhs,
+          const __gnu_debug::_Safe_sequence_base& __rhs,
           __gnu_debug::_Safe_iterator_base*& __rhs_its)
   {
     swap(__lhs_its, __rhs_its);
@@ -84,8 +84,8 @@ namespace
   }
 
   void
-  swap_seq_single(__gnu_debug::_Safe_sequence_base& __lhs,
-                 __gnu_debug::_Safe_sequence_base& __rhs)
+  swap_seq_single(const __gnu_debug::_Safe_sequence_base& __lhs,
+                 const __gnu_debug::_Safe_sequence_base& __rhs)
   {
     swap(__lhs._M_version, __rhs._M_version);
     swap_its(__lhs, __lhs._M_iterators,
@@ -118,17 +118,17 @@ namespace
 
   void
   swap_seq(__gnu_cxx::__mutex& lhs_mutex,
-          __gnu_debug::_Safe_sequence_base& lhs,
+          const __gnu_debug::_Safe_sequence_base& lhs,
           __gnu_cxx::__mutex& rhs_mutex,
-          __gnu_debug::_Safe_sequence_base& rhs)
+          const __gnu_debug::_Safe_sequence_base& rhs)
   {
     lock_and_run(lhs_mutex, rhs_mutex,
                 [&lhs, &rhs]() { swap_seq_single(lhs, rhs); });
   }
 
   void
-  swap_ucont_single(__gnu_debug::_Safe_unordered_container_base& __lhs,
-                   __gnu_debug::_Safe_unordered_container_base& __rhs)
+  swap_ucont_single(const __gnu_debug::_Safe_unordered_container_base& __lhs,
+                   const __gnu_debug::_Safe_unordered_container_base& __rhs)
   {
     swap_seq_single(__lhs, __rhs);
     swap_its(__lhs, __lhs._M_local_iterators,
@@ -139,9 +139,9 @@ namespace
 
   void
   swap_ucont(__gnu_cxx::__mutex& lhs_mutex,
-            __gnu_debug::_Safe_unordered_container_base& lhs,
+            const __gnu_debug::_Safe_unordered_container_base& lhs,
             __gnu_cxx::__mutex& rhs_mutex,
-            __gnu_debug::_Safe_unordered_container_base& rhs)
+            const __gnu_debug::_Safe_unordered_container_base& rhs)
   {
     lock_and_run(lhs_mutex, rhs_mutex,
                 [&lhs, &rhs]() { swap_ucont_single(lhs, rhs); });
@@ -158,8 +158,8 @@ namespace
       }
   }
 
-  void*
-  acquire_sequence_ptr_for_lock(__gnu_debug::_Safe_sequence_base*& seq)
+  const void*
+  acquire_sequence_ptr_for_lock(__gnu_debug::_Safe_sequence_base const*& seq)
   {
 #ifdef __GTHREADS
     if (!__gnu_cxx::__is_single_threaded())
@@ -169,7 +169,7 @@ namespace
   }
 
   void
-  reset_sequence_ptr(__gnu_debug::_Safe_sequence_base*& seq)
+  reset_sequence_ptr(__gnu_debug::_Safe_sequence_base const*& seq)
   {
 #ifdef __GTHREADS
     if (!__gnu_cxx::__is_single_threaded())
@@ -327,7 +327,7 @@ namespace __gnu_debug
 
   void
   _Safe_sequence_base::
-  _M_detach_all()
+  _M_detach_all() const
   {
     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
     detach_all(_M_iterators);
@@ -339,7 +339,7 @@ namespace __gnu_debug
 
   void
   _Safe_sequence_base::
-  _M_detach_singular()
+  _M_detach_singular() const
   {
     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
     for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
@@ -361,7 +361,7 @@ namespace __gnu_debug
 
   void
   _Safe_sequence_base::
-  _M_revalidate_singular()
+  _M_revalidate_singular() const
   {
     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
     for (_Safe_iterator_base* __iter = _M_iterators; __iter;
@@ -375,17 +375,17 @@ namespace __gnu_debug
 
   void
   _Safe_sequence_base::
-  _M_swap(_Safe_sequence_base& __x) noexcept
+  _M_swap(const _Safe_sequence_base& __x) const noexcept
   { swap_seq(_M_get_mutex(), *this, __x._M_get_mutex(), __x); }
 
   __gnu_cxx::__mutex&
   _Safe_sequence_base::
-  _M_get_mutex() noexcept
+  _M_get_mutex() const noexcept
   { return get_safe_base_mutex(this); }
 
   void
   _Safe_sequence_base::
-  _M_attach(_Safe_iterator_base* __it, bool __constant)
+  _M_attach(_Safe_iterator_base* __it, bool __constant) const
   {
     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
     _M_attach_single(__it, __constant);
@@ -393,7 +393,7 @@ namespace __gnu_debug
 
   void
   _Safe_sequence_base::
-  _M_attach_single(_Safe_iterator_base* __it, bool __constant) noexcept
+  _M_attach_single(_Safe_iterator_base* __it, bool __constant) const noexcept
   {
     _Safe_iterator_base*& __its =
       __constant ? _M_const_iterators : _M_iterators;
@@ -405,7 +405,7 @@ namespace __gnu_debug
 
   void
   _Safe_sequence_base::
-  _M_detach(_Safe_iterator_base* __it)
+  _M_detach(_Safe_iterator_base* __it) const
   {
     // Remove __it from this sequence's list
     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
@@ -414,7 +414,7 @@ namespace __gnu_debug
 
   void
   _Safe_sequence_base::
-  _M_detach_single(_Safe_iterator_base* __it) noexcept
+  _M_detach_single(_Safe_iterator_base* __it) const noexcept
   {
     // Remove __it from this sequence's list
     __it->_M_unlink();
@@ -426,7 +426,7 @@ namespace __gnu_debug
 
   void
   _Safe_iterator_base::
-  _M_attach(_Safe_sequence_base* __seq, bool __constant)
+  _M_attach(const _Safe_sequence_base* __seq, bool __constant)
   {
     _M_detach();
 
@@ -443,7 +443,7 @@ namespace __gnu_debug
 
   void
   _Safe_iterator_base::
-  _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept
+  _M_attach_single(const _Safe_sequence_base* __seq, bool __constant) noexcept
   {
     _M_detach_single();
 
@@ -514,14 +514,9 @@ namespace __gnu_debug
   _M_get_mutex() noexcept
   { return _M_sequence->_M_get_mutex(); }
 
-  _Safe_unordered_container_base*
-  _Safe_local_iterator_base::
-  _M_get_container() const noexcept
-  { return static_cast<_Safe_unordered_container_base*>(_M_sequence); }
-
   void
   _Safe_local_iterator_base::
-  _M_attach(_Safe_sequence_base* __cont, bool __constant)
+  _M_attach(const _Safe_unordered_container_base* __cont, bool __constant)
   {
     _M_detach();
 
@@ -538,7 +533,8 @@ namespace __gnu_debug
 
   void
   _Safe_local_iterator_base::
-  _M_attach_single(_Safe_sequence_base* __cont, bool __constant) noexcept
+  _M_attach_single(const _Safe_unordered_container_base* __cont,
+                  bool __constant) noexcept
   {
     _M_detach_single();
 
@@ -577,7 +573,7 @@ namespace __gnu_debug
 
   void
   _Safe_unordered_container_base::
-  _M_detach_all()
+  _M_detach_all() const
   {
     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
     detach_all(_M_iterators);
@@ -595,12 +591,12 @@ namespace __gnu_debug
 
   void
   _Safe_unordered_container_base::
-  _M_swap(_Safe_unordered_container_base& __x) noexcept
+  _M_swap(const _Safe_unordered_container_base& __x) const noexcept
   { swap_ucont(_M_get_mutex(), *this, __x._M_get_mutex(), __x); }
 
   void
   _Safe_unordered_container_base::
-  _M_attach_local(_Safe_iterator_base* __it, bool __constant)
+  _M_attach_local(_Safe_iterator_base* __it, bool __constant) const
   {
     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
     _M_attach_local_single(__it, __constant);
@@ -608,7 +604,7 @@ namespace __gnu_debug
 
   void
   _Safe_unordered_container_base::
-  _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) noexcept
+  _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) const 
noexcept
   {
     _Safe_iterator_base*& __its =
       __constant ? _M_const_local_iterators : _M_local_iterators;
@@ -620,7 +616,7 @@ namespace __gnu_debug
 
   void
   _Safe_unordered_container_base::
-  _M_detach_local(_Safe_iterator_base* __it)
+  _M_detach_local(_Safe_iterator_base* __it) const
   {
     // Remove __it from this container's list
     __gnu_cxx::__scoped_lock sentry(_M_get_mutex());
@@ -629,7 +625,7 @@ namespace __gnu_debug
 
   void
   _Safe_unordered_container_base::
-  _M_detach_local_single(_Safe_iterator_base* __it) noexcept
+  _M_detach_local_single(_Safe_iterator_base* __it) const noexcept
   {
     // Remove __it from this container's list
     __it->_M_unlink();
diff --git a/libstdc++-v3/testsuite/util/testsuite_containers.h 
b/libstdc++-v3/testsuite/util/testsuite_containers.h
index 37491a405dc..ab0107f79e4 100644
--- a/libstdc++-v3/testsuite/util/testsuite_containers.h
+++ b/libstdc++-v3/testsuite/util/testsuite_containers.h
@@ -210,6 +210,9 @@ namespace __gnu_test
        clit = container.cbegin(bn);
        assert( ++clit == container.cend(bn) );
 
+       clit = container.begin(bn);
+       assert( ++clit == container.cend(bn) );
+
        assert( container.begin(bn) != container.cend(bn) );
       }
     };
@@ -304,6 +307,9 @@ namespace __gnu_test
        assert( container.cbegin() != container.cend() );
        assert( container.cbegin() != container.end() );
        assert( container.begin() != container.cend() );
+
+       auto cit = container.begin();
+       assert( cit == container.cbegin() );
       }
   };
 

Reply via email to