On 1/27/26 11:31, Jonathan Wakely wrote:
On Tue, 27 Jan 2026 at 08:30, Tomasz Kaminski <[email protected]> wrote:


On Mon, Jan 26, 2026 at 10:25 PM François Dumont <[email protected]> wrote:
Hi

      libstdc++: [_GLIBCXX_DEBUG] Make constant evaluation compatible

      In a constant evaluation context the _GLIBCXX_DEBUG is working in a
      degradated mode where only iterators are keeping a link to their
container,
      the container won't have a list of its iterators.

      In std::__debug::vector and std::__debug::inplace_vector remove all
calls to
      std::is_constant_evaluated and code associated to it when returning
true. The
      same code is now used in both contexts.
What are the exact benefits of this change? During constant evaluation we 
already
detect all UB caused by access via invalid or past the end pointers, so most of 
the
cases are detected.

As this will have non-trivial impact on compile-times of programs operation on
vector at compile time (including c++26) reflection, I would like to see a more 
concrete
cost (how much longer a decently size example using reflection compilers) vs 
benefits
(examples of situations where this new implementation will detect breach of 
library preconditions,
that are not already detected).

In this new version I've added an example of breach.

_GLIBCXX_DEBUG mode is already known to be costly and is documented as having a performance impact. It seems normal to me that it also has some impact in consteval context.

I don't know much about the reflection subject but _GLIBCXX_DEBUG is optional so maybe it won't be usable along with reflection with this patch. It doesn't sound like a big deal to me but if it is then I'm ready to cut again all debug check when in consteval mode or when reflection is activated.

Yes, I share the same concerns. This is a lot of extra code to run
during constant evaluation, for unclear benefit.

It's a lot of extra code to compile in the consteval expressions but less code written, see the cleanup in <vector> and <inplace_vector>. Future move of containers like the unordered ones will be much more transparent for the _GLIBCXX_DEBUG mode.

_GLIBCXX_DEBUG is already adding extra work to the compiler, I would prefer this extra work to serve a purpose like documented so do minimal checks just forgetting about tracking container's iterators.


This would allow us to diagnose some uses of invalid iterators, like
the topic of https://cplusplus.github.io/LWG/issue2256
Currently that code Just Works, because there is a valid object at
that location, and the rule about invalidating iterators is only
enforced with debug mode, so not during constant evaluation:

#include <vector>
#include <cassert>

constexpr bool f()
{
   typedef std::vector<int> C;
   C c = {1, 2, 3, 4};
   C::iterator i = c.begin() + 1;
   C::iterator j = c.end() - 1;
   assert(*i == 2);
   assert(*j == 4);
   c.erase(c.begin());
   return *i == 3; // Why is this not perfectly fine?!
}
This won't be detected in consteval, container's iterators are not tracked.

static_assert(f());

But I don't think I really care about this. There *is* a valid object,
and if there wasn't, it would fail to compile.

diff --git a/libstdc++-v3/include/debug/forward_list 
b/libstdc++-v3/include/debug/forward_list
index 7d615978000..9a53de8afe2 100644
--- a/libstdc++-v3/include/debug/forward_list
+++ b/libstdc++-v3/include/debug/forward_list
@@ -1030,7 +1030,7 @@ namespace __gnu_debug
     {
       typedef typename std::__debug::forward_list<_Tp, _Alloc>::iterator _It;
 
-      static typename _Distance_traits<_It>::__type
+      static _GLIBCXX20_CONSTEXPR typename _Distance_traits<_It>::__type
       _S_size(const std::__debug::forward_list<_Tp, _Alloc>& __seq)
       {
        return __seq.empty()
diff --git a/libstdc++-v3/include/debug/functions.h 
b/libstdc++-v3/include/debug/functions.h
index 99a0c41758d..9626d344cbc 100644
--- a/libstdc++-v3/include/debug/functions.h
+++ b/libstdc++-v3/include/debug/functions.h
@@ -60,12 +60,8 @@ namespace __gnu_debug
                        unsigned int __line,
                        const char* __function)
     {
-      if (!std::__is_constant_evaluated())
-       {
-         __glibcxx_check_valid_range_at(__first, __last,
-                                        __file, __line, __function);
-       }
-
+      __glibcxx_check_valid_range_at(__first, __last,
+                                    __file, __line, __function);
       return __first;
     }
 
@@ -193,11 +189,14 @@ namespace __gnu_debug
 
   template<typename _Iterator, typename _Sequence, typename _Category,
           typename _InputIterator>
-    inline bool
+    inline _GLIBCXX20_CONSTEXPR bool
     __foreign_iterator(
        const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
        _InputIterator __other, _InputIterator __other_end)
     {
+      if (std::__is_constant_evaluated())
+       return true;
+
       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
       return __foreign_iterator_aux(__it, __other, __other_end, _Integral());
     }
diff --git a/libstdc++-v3/include/debug/helper_functions.h 
b/libstdc++-v3/include/debug/helper_functions.h
index 8ef21684650..d693db16b95 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -116,11 +116,11 @@ namespace __gnu_debug
     }
 
   // An arbitrary iterator pointer is not singular.
-  inline bool
+  inline _GLIBCXX20_CONSTEXPR bool
   __check_singular_aux(const void*) { return false; }
 
   // Defined in <debug/safe_base.h>
-  bool
+  _GLIBCXX20_CONSTEXPR bool
   __check_singular_aux(const class _Safe_iterator_base*);
 
   // We may have an iterator that derives from _Safe_iterator_base but isn't
@@ -129,10 +129,7 @@ namespace __gnu_debug
     _GLIBCXX_CONSTEXPR
     inline bool
     __check_singular(_Iterator const& __x)
-    {
-      return ! std::__is_constant_evaluated()
-              && __gnu_debug::__check_singular_aux(std::__addressof(__x));
-    }
+    { return __gnu_debug::__check_singular_aux(std::__addressof(__x)); }
 
   /** Non-NULL pointers are nonsingular. */
   template<typename _Tp>
diff --git a/libstdc++-v3/include/debug/inplace_vector 
b/libstdc++-v3/include/debug/inplace_vector
index 750b0a7343c..1b01e0b0541 100644
--- a/libstdc++-v3/include/debug/inplace_vector
+++ b/libstdc++-v3/include/debug/inplace_vector
@@ -412,11 +412,6 @@ namespace __debug
        constexpr iterator
        emplace(const_iterator __position, _Args&&... __args)
        {
-         if (std::is_constant_evaluated())
-           return iterator(_Base::emplace(__position.base(),
-                                          std::forward<_Args>(__args)...),
-                           this);
-
          __glibcxx_check_insert(__position);
          const difference_type __offset = __position.base() - _Base::cbegin();
          _Base_iterator __res = _Base::emplace(__position.base(),
@@ -436,10 +431,7 @@ namespace __debug
       constexpr iterator
       insert(const_iterator __position, size_type __n, const _Tp& __x)
       {
-       if (std::is_constant_evaluated())
-         return iterator(_Base::insert(__position.base(), __n, __x), this);
-
-         __glibcxx_check_insert(__position);
+       __glibcxx_check_insert(__position);
        const difference_type __offset = __position.base() - _Base::cbegin();
        _Base_iterator __res = _Base::insert(__position.base(), __n, __x);
        _M_invalidate_after_nth(__offset);
@@ -451,11 +443,6 @@ namespace __debug
        insert(const_iterator __position, _InputIterator __first,
               _InputIterator __last)
        {
-         if (std::is_constant_evaluated())
-           return iterator(_Base::insert(__position.base(),
-                                         __gnu_debug::__unsafe(__first),
-                                         __gnu_debug::__unsafe(__last)), this);
-
          typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
          __glibcxx_check_insert_range(__position, __first, __last, __dist);
 
@@ -469,7 +456,7 @@ namespace __debug
            __res = _Base::insert(__position.base(), __first, __last);
 
          _M_invalidate_after_nth(__offset);
-         return { __res, this };
+         return iterator(__res, this);
        }
 
       template<__detail::__container_compatible_range<_Tp> _Rg>
@@ -488,9 +475,6 @@ namespace __debug
       constexpr iterator
       insert(const_iterator __position, initializer_list<_Tp> __il)
       {
-       if (std::is_constant_evaluated())
-         return iterator(_Base::insert(__position.base(), __il), this);
-
        __glibcxx_check_insert(__position);
        const auto __size = size();
        difference_type __offset = __position.base() - _Base::begin();
@@ -503,9 +487,6 @@ namespace __debug
       constexpr iterator
       erase(const_iterator __position)
       {
-       if (std::is_constant_evaluated())
-         return iterator(_Base::erase(__position.base()), this);
-
        __glibcxx_check_erase(__position);
        difference_type __offset = __position.base() - _Base::cbegin();
        _Base_iterator __res = _Base::erase(__position.base());
@@ -516,10 +497,6 @@ namespace __debug
       constexpr iterator
       erase(const_iterator __first, const_iterator __last)
       {
-       if (std::is_constant_evaluated())
-         return iterator(_Base::erase(__first.base(), __last.base()),
-                         this);
-
        __glibcxx_check_erase_range(__first, __last);
 
        if (__first.base() != __last.base())
diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list
index d06e9e4c2f8..368128cc5a8 100644
--- a/libstdc++-v3/include/debug/list
+++ b/libstdc++-v3/include/debug/list
@@ -1063,7 +1063,7 @@ namespace __gnu_debug
     {
       typedef typename std::__debug::list<_Tp, _Alloc>::iterator _It;
 
-      static typename _Distance_traits<_It>::__type
+      static _GLIBCXX20_CONSTEXPR typename _Distance_traits<_It>::__type
       _S_size(const std::__debug::list<_Tp, _Alloc>& __seq)
       {
        return __seq.empty()
diff --git a/libstdc++-v3/include/debug/macros.h 
b/libstdc++-v3/include/debug/macros.h
index 84ad6d3fe9b..5d0961dfae4 100644
--- a/libstdc++-v3/include/debug/macros.h
+++ b/libstdc++-v3/include/debug/macros.h
@@ -38,10 +38,22 @@
  * the user error and where the error is reported.
  *
  */
+namespace __gnu_debug
+{
+  __attribute__((__always_inline__, __visibility__("default")))
+  inline void
+  __glibcxx_fail()
+  { }
+}
 
 #define _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,_Func)    \
   do {                                                                 \
-    if (__builtin_expect(!bool(_Cond), false))                         \
+    if (std::__is_constant_evaluated())                                        
\
+      {                                                                        
\
+       if (!bool(_Cond))                                               \
+         __gnu_debug::__glibcxx_fail();                                \
+      }                                                                        
\
+    else if (__builtin_expect(!bool(_Cond), false))                    \
       __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func)                
\
        ._ErrMsg._M_error();                                            \
   } while (false)
diff --git a/libstdc++-v3/include/debug/safe_base.h 
b/libstdc++-v3/include/debug/safe_base.h
index 25ac7a4e836..e7fd41cbb0c 100644
--- a/libstdc++-v3/include/debug/safe_base.h
+++ b/libstdc++-v3/include/debug/safe_base.h
@@ -83,37 +83,27 @@ namespace __gnu_debug
     { }
 
     /** Initialize the iterator to reference the sequence pointed to
-     *  by @p __seq. @p __constant is true when we are initializing a
-     *  constant iterator, and false if it is a mutable iterator. Note
-     *  that @p __seq may be NULL, in which case the iterator will be
-     *  singular. Otherwise, the iterator will reference @p __seq and
-     *  be nonsingular.
-     */
+     * by @p __seq. @p __constant is true when we are initializing a
+     * constant iterator, and false if it is a mutable iterator. Note
+     * that @p __seq may be NULL, in which case the iterator will be
+     * singular. Otherwise, the iterator will reference @p __seq and
+     * be nonsingular. */
     _GLIBCXX20_CONSTEXPR
     _Safe_iterator_base(const _Safe_sequence_base* __seq, bool __constant)
     : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
-    {
-      if (!std::__is_constant_evaluated())
-       this->_M_attach(__seq, __constant);
-    }
+    { _M_attach_to(__seq, __constant); }
 
     /** Initializes the iterator to reference the same sequence that
-       @p __x does. @p __constant is true if this is a constant
-       iterator, and false if it is mutable. */
+     * @p __x does. @p __constant is true if this is a constant
+     * iterator, and false if it is mutable. */
     _GLIBCXX20_CONSTEXPR
     _Safe_iterator_base(const _Safe_iterator_base& __x, bool __constant)
     : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
-    {
-      if (!std::__is_constant_evaluated())
-       this->_M_attach(__x._M_sequence, __constant);
-    }
+    { _M_attach_to(__x._M_sequence, __constant); }
 
     _GLIBCXX20_CONSTEXPR
     ~_Safe_iterator_base()
-    {
-      if (!std::__is_constant_evaluated())
-       this->_M_detach();
-    }
+    { _M_detach_sequence(); }
 
     /** For use in _Safe_iterator. */
     __gnu_cxx::__mutex&
@@ -122,10 +112,9 @@ namespace __gnu_debug
     /** Attaches this iterator to the given sequence, detaching it
      * from whatever sequence it was attached to originally. If the
      * new sequence is the NULL pointer, the iterator is left
-     * unattached.
-     */
-    void
-    _M_attach(const _Safe_sequence_base* __seq, bool __constant);
+     * unattached. */
+    _GLIBCXX20_CONSTEXPR void
+    _M_attach_to(const _Safe_sequence_base* __seq, bool __constant);
 
     /** Likewise, but not thread-safe. */
     void
@@ -133,22 +122,40 @@ namespace __gnu_debug
                     bool __constant) _GLIBCXX_USE_NOEXCEPT;
 
     /** Detach the iterator for whatever sequence it is attached to,
-     * if any.
-    */
+     * if any. */
+    _GLIBCXX20_CONSTEXPR void
+    _M_detach_sequence()
+    {
+      if (std::__is_constant_evaluated())
+       _M_sequence = 0;
+      else
+       _M_detach();
+    }
+
+  private:
+    void
+    _M_attach(const _Safe_sequence_base* __seq, bool __constant);
+
     void
     _M_detach();
 
 #if !_GLIBCXX_INLINE_VERSION
-  private:
-    /***************************************************************/
     /** Not-const method preserved for abi backward compatibility. */
     void
     _M_attach(_Safe_sequence_base* __seq, bool __constant);
 
+    /** Not-const method preserved for abi backward compatibility. */
     void
     _M_attach_single(_Safe_sequence_base* __seq,
                     bool __constant) _GLIBCXX_USE_NOEXCEPT;
-    /***************************************************************/
+
+    /* Not-constexpr method preserved for abi backward compatibility. */
+    _GLIBCXX_PURE bool
+    _M_singular() const _GLIBCXX_NOEXCEPT;
+
+    /* Not-constexpr method preserved for abi backward compatibility. */
+    _GLIBCXX_PURE bool
+    _M_can_compare(const _Safe_iterator_base& __x) const _GLIBCXX_USE_NOEXCEPT;
 #endif
 
   public:
@@ -157,22 +164,23 @@ namespace __gnu_debug
     _M_detach_single() _GLIBCXX_USE_NOEXCEPT;
 
     /** Determines if we are attached to the given sequence. */
-    bool
+    _GLIBCXX20_CONSTEXPR bool
     _M_attached_to(const _Safe_sequence_base* __seq) const
     { return _M_sequence == __seq; }
 
     /** Is this iterator singular? */
-    _GLIBCXX_PURE bool
-    _M_singular() const _GLIBCXX_USE_NOEXCEPT;
+    _GLIBCXX20_CONSTEXPR bool
+    _M_is_singular() const _GLIBCXX_USE_NOEXCEPT;
 
     /** Can we compare this iterator to the given iterator @p __x?
-       Returns true if both iterators are nonsingular and reference
-       the same sequence. */
-    _GLIBCXX_PURE bool
-    _M_can_compare(const _Safe_iterator_base& __x) const _GLIBCXX_USE_NOEXCEPT;
+     * Returns true if both iterators are nonsingular and reference
+     * the same sequence. */
+    _GLIBCXX20_CONSTEXPR bool
+    _M_is_comparable(const _Safe_iterator_base& __x) const 
_GLIBCXX_USE_NOEXCEPT
+    { return _M_sequence == __x._M_sequence; }
 
     /** Invalidate the iterator, making it singular. */
-    void
+    _GLIBCXX20_CONSTEXPR void
     _M_invalidate()
     { _M_version = 0; }
 
@@ -194,9 +202,9 @@ namespace __gnu_debug
   /** Iterators that derive from _Safe_iterator_base can be determined singular
    *  or non-singular.
    **/
-  inline bool
+  inline _GLIBCXX20_CONSTEXPR bool
   __check_singular_aux(const _Safe_iterator_base* __x)
-  { return __x->_M_singular(); }
+  { return __x->_M_is_singular(); }
 
   /**
    * @brief Base class that supports tracking of iterators that
@@ -352,6 +360,25 @@ namespace __gnu_debug
     void
     _M_detach_single(_Safe_iterator_base* __it) const _GLIBCXX_USE_NOEXCEPT;
   };
+
+  inline _GLIBCXX20_CONSTEXPR void
+  _Safe_iterator_base::_M_attach_to(const _Safe_sequence_base* __seq,
+                                   bool __constant)
+  {
+    if (std::__is_constant_evaluated())
+      {
+       _M_sequence = __seq;
+       _M_version = _M_sequence->_M_version;
+      }
+    else
+      _M_attach(__seq, __constant);
+  }
+
+  inline _GLIBCXX20_CONSTEXPR bool
+  _Safe_iterator_base::
+  _M_is_singular() const _GLIBCXX_USE_NOEXCEPT
+  { return !_M_sequence || _M_version != _M_sequence->_M_version; }
+
 } // namespace __gnu_debug
 
 #endif
diff --git a/libstdc++-v3/include/debug/safe_container.h 
b/libstdc++-v3/include/debug/safe_container.h
index 32159ba2176..4353f457691 100644
--- a/libstdc++-v3/include/debug/safe_container.h
+++ b/libstdc++-v3/include/debug/safe_container.h
@@ -58,7 +58,10 @@ namespace __gnu_debug
       _GLIBCXX20_CONSTEXPR
       void
       _M_swap_base(const _Safe_container& __x) const noexcept
-      { _Base::_M_swap(__x); }
+      {
+       if (!std::__is_constant_evaluated())
+         _Base::_M_swap(__x);
+      }
 
       _GLIBCXX20_CONSTEXPR
       _Safe_container(_Safe_container&& __x, const _Alloc&, std::true_type)
@@ -69,13 +72,10 @@ namespace __gnu_debug
       _Safe_container(_Safe_container&& __x, const _Alloc& __a, 
std::false_type)
       : _Safe_container()
       {
-       if (!std::__is_constant_evaluated())
-         {
-           if (__x._M_cont().get_allocator() == __a)
-             _M_swap_base(__x);
-           else
-             __x._M_invalidate_all();
-         }
+       if (__x._M_cont().get_allocator() == __a)
+         _M_swap_base(__x);
+       else
+         __x._M_invalidate_all();
       }
 
     protected:
@@ -106,9 +106,6 @@ namespace __gnu_debug
       _Safe_container&
       operator=(_Safe_container&& __x) noexcept
       {
-       if (std::__is_constant_evaluated())
-         return *this;
-
        if (std::__addressof(__x) == this)
          {
            // Standard containers have a valid but unspecified value after
diff --git a/libstdc++-v3/include/debug/safe_iterator.h 
b/libstdc++-v3/include/debug/safe_iterator.h
index 4da3d2bb3d4..a5349bd9b00 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -40,7 +40,6 @@
 #endif
 
 #define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, _BadMsgId, _DiffMsgId) \
-  if (!std::__is_constant_evaluated()) {                               \
   _GLIBCXX_DEBUG_VERIFY((!_Lhs._M_singular() && !_Rhs._M_singular())   \
                        || (_Lhs._M_value_initialized()                 \
                            && _Rhs._M_value_initialized()),            \
@@ -50,8 +49,7 @@
   _GLIBCXX_DEBUG_VERIFY(_Lhs._M_can_compare(_Rhs),                     \
                        _M_message(_DiffMsgId)                          \
                        ._M_iterator(_Lhs, #_Lhs)                       \
-                       ._M_iterator(_Rhs, #_Rhs));                     \
-  }
+                       ._M_iterator(_Rhs, #_Rhs));
 
 #define _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(_Lhs, _Rhs)                  \
   _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_compare_bad,   \
@@ -88,12 +86,12 @@ namespace __gnu_debug
     struct _BeforeBeginHelper
     {
       template<typename _Iterator, typename _Category>
-       static bool
+       static _GLIBCXX20_CONSTEXPR bool
        _S_Is(const _Safe_iterator<_Iterator, _Sequence, _Category>&)
        { return false; }
 
       template<typename _Iterator, typename _Category>
-       static bool
+       static _GLIBCXX20_CONSTEXPR bool
        _S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence, _Category>& 
__it)
        { return __it.base() == __it._M_get_sequence()->_M_base().begin(); }
     };
@@ -104,7 +102,7 @@ namespace __gnu_debug
     {
       typedef _Distance_traits<typename _Sequence::iterator> _DistTraits;
 
-      static typename _DistTraits::__type
+      static _GLIBCXX20_CONSTEXPR typename _DistTraits::__type
       _S_size(const _Sequence& __seq)
       { return std::make_pair(__seq.size(), __dp_exact); }
     };
@@ -131,9 +129,6 @@ namespace __gnu_debug
     : private _Iterator,
       public _Safe_iterator_base
     {
-      typedef _Iterator _Iter_base;
-      typedef _Safe_iterator_base _Safe_base;
-
       typedef std::iterator_traits<_Iterator> _Traits;
 
     protected:
@@ -149,11 +144,8 @@ namespace __gnu_debug
 
       _GLIBCXX20_CONSTEXPR
       _Safe_iterator(const _Safe_iterator& __x, _Unchecked) _GLIBCXX_NOEXCEPT
-      : _Iter_base(__x.base()), _Safe_base()
-      {
-       if (!std::__is_constant_evaluated())
-         _M_attach(__x._M_sequence);
-      }
+      : _Iterator(__x.base()), _Safe_iterator_base()
+      { _M_attach(__x._M_sequence); }
 
     public:
       typedef _Iterator                                        iterator_type;
@@ -169,7 +161,7 @@ namespace __gnu_debug
 
       /// @post the iterator is singular and unattached
       _GLIBCXX20_CONSTEXPR
-      _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { }
+      _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iterator() { }
 
       /**
        * @brief Safe iterator construction from an unsafe iterator and
@@ -181,7 +173,7 @@ namespace __gnu_debug
       _GLIBCXX20_CONSTEXPR
       _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
       _GLIBCXX_NOEXCEPT
-      : _Iter_base(__i), _Safe_base(__seq, _S_constant())
+      : _Iterator(__i), _Safe_iterator_base(__seq, _S_constant())
       { }
 
       /**
@@ -189,11 +181,8 @@ namespace __gnu_debug
        */
       _GLIBCXX20_CONSTEXPR
       _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
-      : _Iter_base(__x.base()), _Safe_base()
+      : _Iterator(__x.base()), _Safe_iterator_base()
       {
-       if (std::__is_constant_evaluated())
-         return;
-
        // _GLIBCXX_RESOLVE_LIB_DEFECTS
        // DR 408. Is vector<reverse_iterator<char*> > forbidden?
        _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
@@ -211,14 +200,8 @@ namespace __gnu_debug
        */
       _GLIBCXX20_CONSTEXPR
       _Safe_iterator(_Safe_iterator&& __x) noexcept
-      : _Iter_base()
+      : _Iterator()
       {
-       if (std::__is_constant_evaluated())
-         {
-           base() = __x.base();
-           return;
-         }
-
        _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
                              || __x._M_value_initialized(),
                              _M_message(__msg_init_copy_singular)
@@ -243,11 +226,8 @@ namespace __gnu_debug
              std::__are_same<_MutableIterator, _OtherIterator>::__value,
                               _Category>::__type>& __x)
        _GLIBCXX_NOEXCEPT
-       : _Iter_base(__x.base())
+       : _Iterator(__x.base())
        {
-         if (std::__is_constant_evaluated())
-           return;
-
          // _GLIBCXX_RESOLVE_LIB_DEFECTS
          // DR 408. Is vector<reverse_iterator<char*> > forbidden?
          _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
@@ -265,12 +245,6 @@ namespace __gnu_debug
       _Safe_iterator&
       operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
       {
-       if (std::__is_constant_evaluated())
-         {
-           base() = __x.base();
-           return *this;
-         }
-
        // _GLIBCXX_RESOLVE_LIB_DEFECTS
        // DR 408. Is vector<reverse_iterator<char*> > forbidden?
        _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
@@ -279,7 +253,8 @@ namespace __gnu_debug
                              ._M_iterator(*this, "this")
                              ._M_iterator(__x, "other"));
 
-       if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
+       if (!std::__is_constant_evaluated()
+           && this->_M_sequence && this->_M_sequence == __x._M_sequence)
          _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
            __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
            base() = __x.base();
@@ -304,12 +279,6 @@ namespace __gnu_debug
       _Safe_iterator&
       operator=(_Safe_iterator&& __x) noexcept
       {
-       if (std::__is_constant_evaluated())
-         {
-           base() = __x.base();
-           return *this;
-         }
-
        _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
                              || __x._M_value_initialized(),
                              _M_message(__msg_copy_singular)
@@ -319,7 +288,8 @@ namespace __gnu_debug
        if (std::__addressof(__x) == this)
          return *this;
 
-       if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
+       if (!std::__is_constant_evaluated()
+           && this->_M_sequence && this->_M_sequence == __x._M_sequence)
          _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
            __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
            base() = __x.base();
@@ -347,12 +317,9 @@ namespace __gnu_debug
       reference
       operator*() const _GLIBCXX_NOEXCEPT
       {
-       if (!std::__is_constant_evaluated())
-         {
-           _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
-                                 _M_message(__msg_bad_deref)
-                                 ._M_iterator(*this, "this"));
-         }
+       _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
+                             _M_message(__msg_bad_deref)
+                             ._M_iterator(*this, "this"));
        return *base();
       }
 
@@ -365,12 +332,9 @@ namespace __gnu_debug
       pointer
       operator->() const _GLIBCXX_NOEXCEPT
       {
-       if (!std::__is_constant_evaluated())
-         {
-           _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
-                                 _M_message(__msg_bad_deref)
-                                 ._M_iterator(*this, "this"));
-         }
+       _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
+                             _M_message(__msg_bad_deref)
+                             ._M_iterator(*this, "this"));
        return base().operator->();
       }
 
@@ -383,19 +347,18 @@ namespace __gnu_debug
       _Safe_iterator&
       operator++() _GLIBCXX_NOEXCEPT
       {
-       if (std::__is_constant_evaluated())
-         {
-           ++base();
-           return *this;
-         }
-
-       _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
+       _GLIBCXX_DEBUG_VERIFY(_M_incrementable(),
                              _M_message(__msg_bad_inc)
                              ._M_iterator(*this, "this"));
-       _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
-         __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+       if (std::__is_constant_evaluated())
          ++base();
-       } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
+       else
+         {
+           _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
+             __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+             ++base();
+           } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
+         }
        return *this;
       }
 
@@ -407,12 +370,9 @@ namespace __gnu_debug
       _Safe_iterator
       operator++(int) _GLIBCXX_NOEXCEPT
       {
-       if (!std::__is_constant_evaluated())
-         {
-           _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
-                                 _M_message(__msg_bad_inc)
-                                 ._M_iterator(*this, "this"));
-         }
+       _GLIBCXX_DEBUG_VERIFY(_M_incrementable(),
+                             _M_message(__msg_bad_inc)
+                             ._M_iterator(*this, "this"));
        _Safe_iterator __ret(*this, _Unchecked());
        ++*this;
        return __ret;
@@ -443,26 +403,40 @@ namespace __gnu_debug
       _GLIBCXX20_CONSTEXPR
       operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; }
 
+      /** Is this iterator singular? */
+      _GLIBCXX20_CONSTEXPR bool
+      _M_singular() const _GLIBCXX_USE_NOEXCEPT
+      { return this->_M_is_singular(); }
+
+      _GLIBCXX20_CONSTEXPR bool
+      _M_can_compare(const _Safe_iterator_base& __x) const 
_GLIBCXX_USE_NOEXCEPT
+      { return this->_M_is_comparable(__x); }
+
       /** Attach iterator to the given sequence. */
-      void
+      _GLIBCXX20_CONSTEXPR void
       _M_attach(const _Safe_sequence_base* __seq)
-      { _Safe_base::_M_attach(__seq, _S_constant()); }
+      { this->_M_attach_to(__seq, _S_constant()); }
 
       /** Likewise, but not thread-safe. */
       void
       _M_attach_single(const _Safe_sequence_base* __seq)
-      { _Safe_base::_M_attach_single(__seq, _S_constant()); }
+      { this->_M_attach_single(__seq, _S_constant()); }
+
+      /** Detach iterator from the sequence. */
+      _GLIBCXX20_CONSTEXPR void
+      _M_detach()
+      { this->_M_detach_sequence(); }
 
       /// Is the iterator dereferenceable?
-      bool
+      _GLIBCXX20_CONSTEXPR bool
       _M_dereferenceable() const
-      { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
+      { return !_M_singular() && !_M_is_end() && !_M_is_before_begin(); }
 
       /// Is the iterator before a dereferenceable one?
-      bool
+      _GLIBCXX20_CONSTEXPR bool
       _M_before_dereferenceable() const
       {
-       if (this->_M_incrementable())
+       if (_M_incrementable())
        {
          _Iterator __base = base();
          return ++__base != _M_get_sequence()->_M_base().end();
@@ -471,33 +445,33 @@ namespace __gnu_debug
       }
 
       /// Is the iterator incrementable?
-      bool
+      _GLIBCXX20_CONSTEXPR bool
       _M_incrementable() const
-      { return !this->_M_singular() && !_M_is_end(); }
+      { return !_M_singular() && !_M_is_end(); }
 
       /// Is the iterator value-initialized?
-      bool
+      _GLIBCXX20_CONSTEXPR bool
       _M_value_initialized() const
-      { return _M_version == 0 && base() == _Iter_base(); }
+      { return _M_version == 0 && base() == _Iterator(); }
 
       // Can we advance the iterator @p __n steps (@p __n may be negative)
-      bool
+      _GLIBCXX20_CONSTEXPR bool
       _M_can_advance(difference_type __n, bool __strict = false) const;
 
       // Can we advance the iterator using @p __dist in @p __way direction.
       template<typename _Diff>
-       bool
+       _GLIBCXX20_CONSTEXPR bool
        _M_can_advance(const std::pair<_Diff, _Distance_precision>& __dist,
                       int __way) const;
 
       // Is the iterator range [*this, __rhs) valid?
-      bool
+      _GLIBCXX20_CONSTEXPR 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<
+      _GLIBCXX20_CONSTEXPR typename __gnu_cxx::__conditional_type<
        _IsConstant::__value, const _Sequence*, _Sequence*>::__type
       _M_get_sequence() const
       {
@@ -513,11 +487,11 @@ namespace __gnu_debug
       _M_get_distance_to(const _Safe_iterator& __rhs) const;
 
       // Get distance from sequence begin up to *this.
-      typename _Distance_traits<_Iterator>::__type
+      _GLIBCXX20_CONSTEXPR typename _Distance_traits<_Iterator>::__type
       _M_get_distance_from_begin() const;
 
       // Get distance from *this to sequence end.
-      typename _Distance_traits<_Iterator>::__type
+      _GLIBCXX20_CONSTEXPR typename _Distance_traits<_Iterator>::__type
       _M_get_distance_to_end() const;
 
       /// Is this iterator equal to the sequence's begin() iterator?
@@ -527,19 +501,19 @@ namespace __gnu_debug
       { return base() == _M_get_sequence()->_M_base().begin(); }
 
       /// Is this iterator equal to the sequence's end() iterator?
-      bool
+      _GLIBCXX20_CONSTEXPR 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
+      _GLIBCXX20_CONSTEXPR 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
+      _GLIBCXX20_CONSTEXPR bool
       _M_is_beginnest() const
       { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); }
 
@@ -690,6 +664,7 @@ namespace __gnu_debug
        *  @brief Iterator postincrement
        *  @pre iterator is incrementable
        */
+      _GLIBCXX20_CONSTEXPR
       _Safe_iterator
       operator++(int) _GLIBCXX_NOEXCEPT
       {
@@ -710,19 +685,20 @@ namespace __gnu_debug
       _Safe_iterator&
       operator--() _GLIBCXX_NOEXCEPT
       {
-       if (std::__is_constant_evaluated())
-         {
-           --this->base();
-           return *this;
-         }
-
        _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
                              _M_message(__msg_bad_dec)
                              ._M_iterator(*this, "this"));
-       _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
-         __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+
+       if (std::__is_constant_evaluated())
          --this->base();
-       } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
+       else
+         {
+           _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
+             __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+             --this->base();
+           } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
+         }
+
        return *this;
       }
 
@@ -730,6 +706,7 @@ namespace __gnu_debug
        *  @brief Iterator postdecrement
        *  @pre iterator is decrementable
        */
+      _GLIBCXX20_CONSTEXPR
       _Safe_iterator
       operator--(int) _GLIBCXX_NOEXCEPT
       {
@@ -744,7 +721,7 @@ namespace __gnu_debug
       // ------ Utilities ------
 
       // Is the iterator decrementable?
-      bool
+      _GLIBCXX20_CONSTEXPR bool
       _M_decrementable() const
       { return !this->_M_singular() && !this->_M_is_begin(); }
     };
@@ -838,7 +815,7 @@ namespace __gnu_debug
 #endif
 
       // Is the iterator range [*this, __rhs) valid?
-      bool
+      _GLIBCXX20_CONSTEXPR bool
       _M_valid_range(const _Safe_iterator& __rhs,
                     std::pair<difference_type,
                               _Distance_precision>& __dist) const;
@@ -864,12 +841,9 @@ namespace __gnu_debug
       _Safe_iterator
       operator++(int) _GLIBCXX_NOEXCEPT
       {
-       if (!std::__is_constant_evaluated())
-         {
-           _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
-                                 _M_message(__msg_bad_inc)
-                                 ._M_iterator(*this, "this"));
-         }
+       _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
+                             _M_message(__msg_bad_inc)
+                             ._M_iterator(*this, "this"));
        _Safe_iterator __ret(*this, _Unchecked());
        ++*this;
        return __ret;
@@ -896,12 +870,9 @@ namespace __gnu_debug
       _Safe_iterator
       operator--(int) _GLIBCXX_NOEXCEPT
       {
-       if (!std::__is_constant_evaluated())
-         {
-           _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
-                                 _M_message(__msg_bad_dec)
-                                 ._M_iterator(*this, "this"));
-         }
+       _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
+                             _M_message(__msg_bad_dec)
+                             ._M_iterator(*this, "this"));
        _Safe_iterator __ret(*this, _Unchecked());
        --*this;
        return __ret;
@@ -913,13 +884,10 @@ namespace __gnu_debug
       reference
       operator[](difference_type __n) const _GLIBCXX_NOEXCEPT
       {
-       if (!std::__is_constant_evaluated())
-         {
-           _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
-                                 && this->_M_can_advance(__n + 1),
-                                 _M_message(__msg_iter_subscript_oob)
-                                 ._M_iterator(*this)._M_integer(__n));
-         }
+       _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
+                             && this->_M_can_advance(__n + 1),
+                             _M_message(__msg_iter_subscript_oob)
+                             ._M_iterator(*this)._M_integer(__n));
        return this->base()[__n];
       }
 
@@ -927,19 +895,18 @@ namespace __gnu_debug
       _Safe_iterator&
       operator+=(difference_type __n) _GLIBCXX_NOEXCEPT
       {
-       if (std::__is_constant_evaluated())
-         {
-           this->base() += __n;
-           return *this;
-         }
-
        _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
                              _M_message(__msg_advance_oob)
                              ._M_iterator(*this)._M_integer(__n));
-       _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
-         __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+       if (std::__is_constant_evaluated())
          this->base() += __n;
-       } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
+       else
+         {
+           _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
+             __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+             this->base() += __n;
+           } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
+         }
        return *this;
       }
 
@@ -947,19 +914,18 @@ namespace __gnu_debug
       _Safe_iterator&
       operator-=(difference_type __n) _GLIBCXX_NOEXCEPT
       {
-       if (std::__is_constant_evaluated())
-         {
-           this->base() -= __n;
-           return *this;
-         }
-
        _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
                              _M_message(__msg_retreat_oob)
                              ._M_iterator(*this)._M_integer(__n));
-       _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
-         __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+       if (std::__is_constant_evaluated())
          this->base() -= __n;
-       } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
+       else
+         {
+           _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
+             __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+             this->base() -= __n;
+           } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END
+         }
        return *this;
       }
 
@@ -983,6 +949,7 @@ namespace __gnu_debug
       }
 #else
       _GLIBCXX_NODISCARD
+      _GLIBCXX20_CONSTEXPR
       friend bool
       operator<(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
       {
@@ -991,6 +958,7 @@ namespace __gnu_debug
       }
 
       _GLIBCXX_NODISCARD
+      _GLIBCXX20_CONSTEXPR
       friend bool
       operator<(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
       {
@@ -999,6 +967,7 @@ namespace __gnu_debug
       }
 
       _GLIBCXX_NODISCARD
+      _GLIBCXX20_CONSTEXPR
       friend bool
       operator<=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
       {
@@ -1007,6 +976,7 @@ namespace __gnu_debug
       }
 
       _GLIBCXX_NODISCARD
+      _GLIBCXX20_CONSTEXPR
       friend bool
       operator<=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
       {
@@ -1015,6 +985,7 @@ namespace __gnu_debug
       }
 
       _GLIBCXX_NODISCARD
+      _GLIBCXX20_CONSTEXPR
       friend bool
       operator>(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
       {
@@ -1023,6 +994,7 @@ namespace __gnu_debug
       }
 
       _GLIBCXX_NODISCARD
+      _GLIBCXX20_CONSTEXPR
       friend bool
       operator>(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
       {
@@ -1031,6 +1003,7 @@ namespace __gnu_debug
       }
 
       _GLIBCXX_NODISCARD
+      _GLIBCXX20_CONSTEXPR
       friend bool
       operator>=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
       {
@@ -1039,6 +1012,7 @@ namespace __gnu_debug
       }
 
       _GLIBCXX_NODISCARD
+      _GLIBCXX20_CONSTEXPR
       friend bool
       operator>=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT
       {
@@ -1074,12 +1048,9 @@ namespace __gnu_debug
       friend _Self
       operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
       {
-       if (!std::__is_constant_evaluated())
-         {
-           _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n),
-                                 _M_message(__msg_advance_oob)
-                                 ._M_iterator(__x)._M_integer(__n));
-         }
+       _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n),
+                             _M_message(__msg_advance_oob)
+                             ._M_iterator(__x)._M_integer(__n));
        return _Safe_iterator(__x.base() + __n, __x._M_sequence);
       }
 
@@ -1088,12 +1059,9 @@ namespace __gnu_debug
       friend _Self
       operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT
       {
-       if (!std::__is_constant_evaluated())
-         {
-           _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n),
-                                 _M_message(__msg_advance_oob)
-                                 ._M_iterator(__x)._M_integer(__n));
-         }
+       _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n),
+                             _M_message(__msg_advance_oob)
+                             ._M_iterator(__x)._M_integer(__n));
        return _Safe_iterator(__n + __x.base(), __x._M_sequence);
       }
 
@@ -1102,12 +1070,9 @@ namespace __gnu_debug
       friend _Self
       operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT
       {
-       if (!std::__is_constant_evaluated())
-         {
-           _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n),
-                                 _M_message(__msg_retreat_oob)
-                                 ._M_iterator(__x)._M_integer(__n));
-         }
+       _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n),
+                             _M_message(__msg_retreat_oob)
+                             ._M_iterator(__x)._M_integer(__n));
        return _Safe_iterator(__x.base() - __n, __x._M_sequence);
       }
     };
@@ -1121,12 +1086,7 @@ namespace __gnu_debug
                  const _Safe_iterator<_Iterator, _Sequence,
                                       _Category>& __last,
                  typename _Distance_traits<_Iterator>::__type& __dist)
-    {
-      if (std::__is_constant_evaluated())
-       return true;
-
-      return __first._M_valid_range(__last, __dist);
-    }
+    { return __first._M_valid_range(__last, __dist); }
 
   template<typename _Iterator, typename _Sequence, typename _Category>
     _GLIBCXX20_CONSTEXPR
@@ -1136,9 +1096,6 @@ namespace __gnu_debug
                  const _Safe_iterator<_Iterator, _Sequence,
                                       _Category>& __last)
     {
-      if (std::__is_constant_evaluated())
-       return true;
-
       typename _Distance_traits<_Iterator>::__type __dist;
       return __first._M_valid_range(__last, __dist);
     }
@@ -1149,12 +1106,7 @@ namespace __gnu_debug
     inline bool
     __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
                  _Size __n)
-    { 
-      if (std::__is_constant_evaluated())
-       return true;
-
-      return __it._M_can_advance(__n);
-    }
+    { return __it._M_can_advance(__n); }
 
   template<typename _Iterator, typename _Sequence, typename _Category,
           typename _Diff>
@@ -1163,12 +1115,7 @@ namespace __gnu_debug
     __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
                  const std::pair<_Diff, _Distance_precision>& __dist,
                  int __way)
-    {
-      if (std::__is_constant_evaluated())
-       return true;
-    
-      return __it._M_can_advance(__dist, __way);
-    }
+    { return __it._M_can_advance(__dist, __way); }
 
   template<typename _Iterator, typename _Sequence>
     _GLIBCXX20_CONSTEXPR _Iterator
diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc 
b/libstdc++-v3/include/debug/safe_iterator.tcc
index 715eceb92f3..3a4bc106ae5 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -34,7 +34,7 @@
 namespace __gnu_debug
 {
   template<typename _Iterator, typename _Sequence, typename _Category>
-    typename _Distance_traits<_Iterator>::__type
+    _GLIBCXX20_CONSTEXPR typename _Distance_traits<_Iterator>::__type
     _Safe_iterator<_Iterator, _Sequence, _Category>::
     _M_get_distance_from_begin() const
     {
@@ -58,7 +58,7 @@ namespace __gnu_debug
     }
 
   template<typename _Iterator, typename _Sequence, typename _Category>
-    typename _Distance_traits<_Iterator>::__type
+    _GLIBCXX20_CONSTEXPR typename _Distance_traits<_Iterator>::__type
     _Safe_iterator<_Iterator, _Sequence, _Category>::
     _M_get_distance_to_end() const
     {
@@ -82,7 +82,7 @@ namespace __gnu_debug
     }
 
   template<typename _Iterator, typename _Sequence, typename _Category>
-    bool
+    _GLIBCXX20_CONSTEXPR bool
     _Safe_iterator<_Iterator, _Sequence, _Category>::
     _M_can_advance(difference_type __n, bool __strict) const
     {
@@ -109,7 +109,7 @@ namespace __gnu_debug
 
   template<typename _Iterator, typename _Sequence, typename _Category>
     template<typename _Diff>
-      bool
+      _GLIBCXX20_CONSTEXPR bool
       _Safe_iterator<_Iterator, _Sequence, _Category>::
       _M_can_advance(const std::pair<_Diff, _Distance_precision>& __dist,
                     int __way) const
@@ -191,7 +191,7 @@ namespace __gnu_debug
     }
 
   template<typename _Iterator, typename _Sequence, typename _Category>
-    bool
+    _GLIBCXX20_CONSTEXPR bool
     _Safe_iterator<_Iterator, _Sequence, _Category>::
     _M_valid_range(const _Safe_iterator& __rhs,
                   std::pair<difference_type, _Distance_precision>& __dist,
@@ -221,7 +221,7 @@ namespace __gnu_debug
     }
 
   template<typename _Iterator, typename _Sequence>
-    bool
+    _GLIBCXX20_CONSTEXPR bool
     _Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag>::
     _M_valid_range(const _Safe_iterator& __rhs,
                   std::pair<difference_type,
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h 
b/libstdc++-v3/include/debug/safe_local_iterator.h
index d37168a040b..391ddb5cde1 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.h
+++ b/libstdc++-v3/include/debug/safe_local_iterator.h
@@ -65,9 +65,6 @@ namespace __gnu_debug
     : private _Iterator
     , public _Safe_local_iterator_base
     {
-      typedef _Iterator _Iter_base;
-      typedef _Safe_local_iterator_base _Safe_base;
-
       typedef typename _UContainer::size_type size_type;
 
       typedef std::iterator_traits<_Iterator> _Traits;
@@ -87,7 +84,7 @@ namespace __gnu_debug
 
       _Safe_local_iterator(const _Safe_local_iterator& __x,
                           _Unchecked) noexcept
-      : _Iter_base(__x.base())
+      : _Iterator(__x.base())
       { _M_attach(__x._M_safe_container()); }
 
     public:
@@ -99,7 +96,7 @@ namespace __gnu_debug
       typedef typename _Traits::pointer                        pointer;
 
       /// @post the iterator is singular and unattached
-      _Safe_local_iterator() noexcept : _Iter_base() { }
+      _Safe_local_iterator() noexcept : _Iterator() { }
 
       /**
        * @brief Safe iterator construction from an unsafe iterator and
@@ -110,14 +107,14 @@ namespace __gnu_debug
        */
       _Safe_local_iterator(_Iterator __i,
                           const _Safe_unordered_container_base* __cont)
-      : _Iter_base(__i), _Safe_base(__cont, _S_constant())
+      : _Iterator(__i), _Safe_local_iterator_base(__cont, _S_constant())
       { }
 
       /**
        * @brief Copy construction.
        */
       _Safe_local_iterator(const _Safe_local_iterator& __x) noexcept
-      : _Iter_base(__x.base())
+      : _Iterator(__x.base())
       {
        // _GLIBCXX_RESOLVE_LIB_DEFECTS
        // DR 408. Is vector<reverse_iterator<char*> > forbidden?
@@ -134,7 +131,7 @@ namespace __gnu_debug
        * @post __x is singular and unattached
        */
       _Safe_local_iterator(_Safe_local_iterator&& __x) noexcept
-      : _Iter_base()
+      : _Iterator()
       {
        _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
                              || __x._M_value_initialized(),
@@ -157,7 +154,7 @@ namespace __gnu_debug
          typename __gnu_cxx::__enable_if<_IsConstant::__value &&
            std::__are_same<_MutableIterator, _OtherIterator>::__value,
                                          _UContainer>::__type>& __x) noexcept
-       : _Iter_base(__x.base())
+       : _Iterator(__x.base())
        {
          // _GLIBCXX_RESOLVE_LIB_DEFECTS
          // DR 408. Is vector<reverse_iterator<char*> > forbidden?
@@ -240,7 +237,7 @@ namespace __gnu_debug
       reference
       operator*() const
       {
-       _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
+       _GLIBCXX_DEBUG_VERIFY(_M_dereferenceable(),
                              _M_message(__msg_bad_deref)
                              ._M_iterator(*this, "this"));
        return *base();
@@ -253,7 +250,7 @@ namespace __gnu_debug
       pointer
       operator->() const
       {
-       _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
+       _GLIBCXX_DEBUG_VERIFY(_M_dereferenceable(),
                              _M_message(__msg_bad_deref)
                              ._M_iterator(*this, "this"));
        return base().operator->();
@@ -267,7 +264,7 @@ namespace __gnu_debug
       _Safe_local_iterator&
       operator++()
       {
-       _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
+       _GLIBCXX_DEBUG_VERIFY(_M_incrementable(),
                              _M_message(__msg_bad_inc)
                              ._M_iterator(*this, "this"));
        __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
@@ -282,7 +279,7 @@ namespace __gnu_debug
       _Safe_local_iterator
       operator++(int)
       {
-       _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
+       _GLIBCXX_DEBUG_VERIFY(_M_incrementable(),
                              _M_message(__msg_bad_inc)
                              ._M_iterator(*this, "this"));
        _Safe_local_iterator __ret(*this, _Unchecked{});
@@ -318,30 +315,39 @@ namespace __gnu_debug
        */
       operator _Iterator() const { return *this; }
 
+      /** Is this iterator singular? */
+      _GLIBCXX20_CONSTEXPR bool
+      _M_singular() const noexcept
+      { return this->_M_is_singular(); }
+
+      _GLIBCXX20_CONSTEXPR bool
+      _M_can_compare(const _Safe_iterator_base& __x) const noexcept
+      { return this->_M_is_comparable(__x); }
+
       /** Attach iterator to the given unordered container. */
-      void
+      _GLIBCXX20_CONSTEXPR void
       _M_attach(const _Safe_unordered_container_base* __cont)
-      { _Safe_base::_M_attach(__cont, _S_constant()); }
+      { _Safe_local_iterator_base::_M_attach(__cont, _S_constant()); }
 
       /** Likewise, but not thread-safe. */
       void
       _M_attach_single(const _Safe_unordered_container_base* __cont)
-      { _Safe_base::_M_attach_single(__cont, _S_constant()); }
+      { _Safe_local_iterator_base::_M_attach_single(__cont, _S_constant()); }
 
       /// Is the iterator dereferenceable?
       bool
       _M_dereferenceable() const
-      { return !this->_M_singular() && !_M_is_end(); }
+      { return !_M_singular() && !_M_is_end(); }
 
       /// Is the iterator incrementable?
       bool
       _M_incrementable() const
-      { return !this->_M_singular() && !_M_is_end(); }
+      { return !_M_singular() && !_M_is_end(); }
 
       /// Is the iterator value-initialized?
       bool
       _M_value_initialized() const
-      { return _M_version == 0 && base() == _Iter_base{}; }
+      { return _M_version == 0 && base() == _Iterator{}; }
 
       // Is the iterator range [*this, __rhs) valid?
       bool
diff --git a/libstdc++-v3/include/debug/safe_sequence.h 
b/libstdc++-v3/include/debug/safe_sequence.h
index e7658bb26a7..4415f689c9f 100644
--- a/libstdc++-v3/include/debug/safe_sequence.h
+++ b/libstdc++-v3/include/debug/safe_sequence.h
@@ -110,6 +110,10 @@ namespace __gnu_debug
   template<typename _Sequence>
     class _Safe_sequence : public _Safe_sequence_base
     {
+      template<typename _Predicate>
+       void
+       _M_invalidate_if_impl(_Predicate __pred) const;
+
     public:
       /** Invalidates all iterators @c x that reference this sequence,
          are not singular, and for which @c __pred(x) returns @c
@@ -117,7 +121,13 @@ namespace __gnu_debug
          in the safe ones. */
       template<typename _Predicate>
        _GLIBCXX20_CONSTEXPR void
-       _M_invalidate_if(_Predicate __pred) const;
+       _M_invalidate_if(_Predicate __pred) const
+       {
+         if (std::__is_constant_evaluated())
+           return;
+
+         _M_invalidate_if_impl(__pred);
+       }
 
       /** Transfers all iterators @c x that reference @c from sequence,
          are not singular, and for which @c __pred(x) returns @c
diff --git a/libstdc++-v3/include/debug/safe_sequence.tcc 
b/libstdc++-v3/include/debug/safe_sequence.tcc
index 884478fad9d..f55767258be 100644
--- a/libstdc++-v3/include/debug/safe_sequence.tcc
+++ b/libstdc++-v3/include/debug/safe_sequence.tcc
@@ -33,13 +33,10 @@ namespace __gnu_debug
 {
   template<typename _Sequence>
     template<typename _Predicate>
-      _GLIBCXX20_CONSTEXPR void
+      void
       _Safe_sequence<_Sequence>::
-      _M_invalidate_if(_Predicate __pred) const
+      _M_invalidate_if_impl(_Predicate __pred) const
       {
-       if (std::__is_constant_evaluated())
-         return;
-
        typedef typename _Sequence::iterator iterator;
        typedef typename _Sequence::const_iterator const_iterator;
 
diff --git a/libstdc++-v3/include/debug/safe_unordered_base.h 
b/libstdc++-v3/include/debug/safe_unordered_base.h
index 603ceff9a86..427067aaf4e 100644
--- a/libstdc++-v3/include/debug/safe_unordered_base.h
+++ b/libstdc++-v3/include/debug/safe_unordered_base.h
@@ -74,9 +74,9 @@ namespace __gnu_debug
        iterator, and false if it is mutable. */
     _Safe_local_iterator_base(const _Safe_local_iterator_base& __x,
                              bool __constant)
-    { this->_M_attach(__x._M_safe_container(), __constant); }
+    { _M_attach(__x._M_safe_container(), __constant); }
 
-    ~_Safe_local_iterator_base() { this->_M_detach(); }
+    ~_Safe_local_iterator_base() { _M_detach(); }
 
     /** Attaches this iterator to the given container, detaching it
      * from whatever container it was attached to originally. If the
diff --git a/libstdc++-v3/include/debug/vector 
b/libstdc++-v3/include/debug/vector
index 61e5ff78a7a..ca9c9169226 100644
--- a/libstdc++-v3/include/debug/vector
+++ b/libstdc++-v3/include/debug/vector
@@ -103,7 +103,7 @@ namespace __gnu_debug
 
       size_type _M_guaranteed_capacity;
 
-      bool
+      _GLIBCXX20_CONSTEXPR bool
       _M_requires_reallocation(size_type __elements) const _GLIBCXX_NOEXCEPT
       { return __elements > _M_seq().capacity(); }
 
@@ -213,8 +213,8 @@ namespace __debug
        _GLIBCXX20_CONSTEXPR
        vector(_InputIterator __first, _InputIterator __last,
               const _Allocator& __a = _Allocator())
-       : _Base(__gnu_debug::__base(std::__is_constant_evaluated() ? __first
-                 : __glibcxx_check_valid_constructor_range(__first, __last)),
+       : _Base(__gnu_debug::__base(
+                 __glibcxx_check_valid_constructor_range(__first, __last)),
                __gnu_debug::__base(__last), __a) { }
 
 #if __cplusplus < 201103L
@@ -277,11 +277,8 @@ namespace __debug
       operator=(initializer_list<value_type> __l)
       {
        _Base::operator=(__l);
-       if (!std::__is_constant_evaluated())
-         {
-           this->_M_invalidate_all();
-           this->_M_update_guaranteed_capacity();
-         }
+       this->_M_invalidate_all();
+       this->_M_update_guaranteed_capacity();
        return *this;
       }
 #endif
@@ -296,10 +293,6 @@ namespace __debug
        void
        assign(_InputIterator __first, _InputIterator __last)
        {
-         if (std::__is_constant_evaluated())
-           return _Base::assign(__gnu_debug::__unsafe(__first),
-                                __gnu_debug::__unsafe(__last));
-
          typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
          __glibcxx_check_valid_range2(__first, __last, __dist);
 
@@ -318,11 +311,8 @@ namespace __debug
       assign(size_type __n, const _Tp& __u)
       {
        _Base::assign(__n, __u);
-       if (!std::__is_constant_evaluated())
-         {
-           this->_M_invalidate_all();
-           this->_M_update_guaranteed_capacity();
-         }
+       this->_M_invalidate_all();
+       this->_M_update_guaranteed_capacity();
       }
 
 #if __cplusplus >= 201103L
@@ -331,11 +321,8 @@ namespace __debug
       assign(initializer_list<value_type> __l)
       {
        _Base::assign(__l);
-       if (!std::__is_constant_evaluated())
-         {
-           this->_M_invalidate_all();
-           this->_M_update_guaranteed_capacity();
-         }
+       this->_M_invalidate_all();
+       this->_M_update_guaranteed_capacity();
       }
 #endif
 
@@ -425,9 +412,6 @@ namespace __debug
       void
       resize(size_type __sz)
       {
-       if (std::__is_constant_evaluated())
-         return _Base::resize(__sz);
-
        bool __realloc = this->_M_requires_reallocation(__sz);
        if (__sz < this->size())
          this->_M_invalidate_after_nth(__sz);
@@ -441,9 +425,6 @@ namespace __debug
       void
       resize(size_type __sz, const _Tp& __c)
       {
-       if (std::__is_constant_evaluated())
-         return _Base::resize(__sz, __c);
-
        bool __realloc = this->_M_requires_reallocation(__sz);
        if (__sz < this->size())
          this->_M_invalidate_after_nth(__sz);
@@ -471,9 +452,6 @@ namespace __debug
       void
       shrink_to_fit()
       {
-       if (std::__is_constant_evaluated())
-         return _Base::shrink_to_fit();
-
        if (_Base::_M_shrink_to_fit())
          {
            this->_M_guaranteed_capacity = _Base::capacity();
@@ -487,9 +465,6 @@ namespace __debug
       size_type
       capacity() const _GLIBCXX_NOEXCEPT
       {
-       if (std::__is_constant_evaluated())
-         return _Base::capacity();
-
 #ifdef _GLIBCXX_DEBUG_PEDANTIC
        return this->_M_guaranteed_capacity;
 #else
@@ -503,9 +478,6 @@ namespace __debug
       void
       reserve(size_type __n)
       {
-       if (std::__is_constant_evaluated())
-         return _Base::reserve(__n);
-
        bool __realloc = this->_M_requires_reallocation(__n);
        _Base::reserve(__n);
        if (__n > this->_M_guaranteed_capacity)
@@ -580,9 +552,6 @@ namespace __debug
       void
       push_back(const _Tp& __x)
       {
-       if (std::__is_constant_evaluated())
-         return _Base::push_back(__x);
-
        bool __realloc = this->_M_requires_reallocation(this->size() + 1);
        _Base::push_back(__x);
        if (__realloc)
@@ -607,9 +576,6 @@ namespace __debug
 #endif
        emplace_back(_Args&&... __args)
        {
-         if (std::__is_constant_evaluated())
-           return _Base::emplace_back(std::forward<_Args>(__args)...);
-
          bool __realloc = this->_M_requires_reallocation(this->size() + 1);
          _Base::emplace_back(std::forward<_Args>(__args)...);
          if (__realloc)
@@ -625,11 +591,8 @@ namespace __debug
       void
       pop_back() _GLIBCXX_NOEXCEPT
       {
-       if (!std::__is_constant_evaluated())
-         {
-           __glibcxx_check_nonempty();
-           this->_M_invalidate_if(_Equal(--_Base::end()));
-         }
+       __glibcxx_check_nonempty();
+       this->_M_invalidate_if(_Equal(--_Base::end()));
        _Base::pop_back();
       }
 
@@ -639,11 +602,6 @@ namespace __debug
        iterator
        emplace(const_iterator __position, _Args&&... __args)
        {
-         if (std::__is_constant_evaluated())
-           return iterator(_Base::emplace(__position.base(),
-                                          std::forward<_Args>(__args)...),
-                           this);
-
          __glibcxx_check_insert(__position);
          bool __realloc = this->_M_requires_reallocation(this->size() + 1);
          difference_type __offset = __position.base() - _Base::cbegin();
@@ -666,9 +624,6 @@ namespace __debug
       insert(iterator __position, const _Tp& __x)
 #endif
       {
-       if (std::__is_constant_evaluated())
-         return iterator(_Base::insert(__position.base(), __x), this);
-
        __glibcxx_check_insert(__position);
        bool __realloc = this->_M_requires_reallocation(this->size() + 1);
        difference_type __offset = __position.base() - _Base::begin();
@@ -700,9 +655,6 @@ namespace __debug
       iterator
       insert(const_iterator __position, size_type __n, const _Tp& __x)
       {
-       if (std::__is_constant_evaluated())
-         return iterator(_Base::insert(__position.base(), __n, __x), this);
-
        __glibcxx_check_insert(__position);
        bool __realloc = this->_M_requires_reallocation(this->size() + __n);
        difference_type __offset = __position.base() - _Base::cbegin();
@@ -738,11 +690,6 @@ namespace __debug
        insert(const_iterator __position,
               _InputIterator __first, _InputIterator __last)
        {
-         if (std::__is_constant_evaluated())
-           return iterator(_Base::insert(__position.base(),
-                                         __gnu_debug::__unsafe(__first),
-                                         __gnu_debug::__unsafe(__last)), this);
-
          typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
          __glibcxx_check_insert_range(__position, __first, __last, __dist);
 
@@ -802,9 +749,6 @@ namespace __debug
       erase(iterator __position)
 #endif
       {
-       if (std::__is_constant_evaluated())
-         return iterator(_Base::erase(__position.base()), this);
-
        __glibcxx_check_erase(__position);
        difference_type __offset = __position.base() - _Base::begin();
        _Base_iterator __res = _Base::erase(__position.base());
@@ -820,9 +764,6 @@ namespace __debug
       erase(iterator __first, iterator __last)
 #endif
       {
-       if (std::__is_constant_evaluated())
-         return iterator(_Base::erase(__first.base(), __last.base()), this);
-
        // _GLIBCXX_RESOLVE_LIB_DEFECTS
        // 151. can't currently clear() empty container
        __glibcxx_check_erase_range(__first, __last);
@@ -848,8 +789,7 @@ namespace __debug
       swap(vector& __x)
       _GLIBCXX_NOEXCEPT_IF( noexcept(declval<_Base&>().swap(__x)) )
       {
-       if (!std::__is_constant_evaluated())
-         _Safe::_M_swap(__x);
+       _Safe::_M_swap(__x);
        _Base::swap(__x);
        std::swap(this->_M_guaranteed_capacity, __x._M_guaranteed_capacity);
       }
@@ -859,8 +799,7 @@ namespace __debug
       clear() _GLIBCXX_NOEXCEPT
       {
        _Base::clear();
-       if (!std::__is_constant_evaluated())
-         this->_M_invalidate_all();
+       this->_M_invalidate_all();
       }
 
       _GLIBCXX20_CONSTEXPR
@@ -879,14 +818,11 @@ namespace __debug
          auto __old_capacity = _Base::capacity();
          auto __old_size = _Base::size();
          _Base::assign_range(__rg);
-         if (!std::__is_constant_evaluated())
-           {
-             if (_Base::capacity() != __old_capacity)
-               this->_M_invalidate_all();
-             else if (_Base::size() < __old_size)
-               this->_M_invalidate_after_nth(_Base::size());
-             this->_M_update_guaranteed_capacity();
-           }
+         if (_Base::capacity() != __old_capacity)
+           this->_M_invalidate_all();
+         else if (_Base::size() < __old_size)
+           this->_M_invalidate_after_nth(_Base::size());
+         this->_M_update_guaranteed_capacity();
        }
 
       template<__detail::__container_compatible_range<_Tp> _Rg>
@@ -895,12 +831,9 @@ namespace __debug
        {
          auto __old_capacity = _Base::capacity();
          auto __res = _Base::insert_range(__pos.base(), __rg);
-         if (!std::__is_constant_evaluated())
-           {
-             if (_Base::capacity() != __old_capacity)
-               this->_M_invalidate_all();
-             this->_M_update_guaranteed_capacity();
-           }
+         if (_Base::capacity() != __old_capacity)
+           this->_M_invalidate_all();
+         this->_M_update_guaranteed_capacity();
          return iterator(__res, this);
        }
 
@@ -910,17 +843,14 @@ namespace __debug
        {
          auto __old_capacity = _Base::capacity();
          _Base::append_range(__rg);
-         if (!std::__is_constant_evaluated())
-           {
-             if (_Base::capacity() != __old_capacity)
-               this->_M_invalidate_all();
-             this->_M_update_guaranteed_capacity();
-           }
+         if (_Base::capacity() != __old_capacity)
+           this->_M_invalidate_all();
+         this->_M_update_guaranteed_capacity();
        }
 #endif
 
     private:
-      void
+      _GLIBCXX20_CONSTEXPR void
       _M_invalidate_after_nth(difference_type __n) _GLIBCXX_NOEXCEPT
       {
        typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc
index 3e6f286bc0a..a79dab9497d 100644
--- a/libstdc++-v3/src/c++11/debug.cc
+++ b/libstdc++-v3/src/c++11/debug.cc
@@ -346,7 +346,7 @@ namespace __gnu_debug
       {
        _Safe_iterator_base* __old = __iter;
        __iter = __iter->_M_next;
-       if (__old->_M_singular())
+       if (__old->_M_is_singular())
          __old->_M_detach_single();
       }
 
@@ -354,7 +354,7 @@ namespace __gnu_debug
       {
        _Safe_iterator_base* __old = __iter2;
        __iter2 = __iter2->_M_next;
-       if (__old->_M_singular())
+       if (__old->_M_is_singular())
          __old->_M_detach_single();
       }
   }
@@ -462,7 +462,7 @@ namespace __gnu_debug
     __it->_M_unlink();
     if (_M_const_iterators == __it)
       _M_const_iterators = __it->_M_next;
-    if (_M_iterators == __it)
+    else if (_M_iterators == __it)
       _M_iterators = __it->_M_next;
   }
 
@@ -541,15 +541,17 @@ namespace __gnu_debug
     _M_next = 0;
   }
 
+#if !_GLIBCXX_INLINE_VERSION
   bool
   _Safe_iterator_base::
   _M_singular() const noexcept
-  { return !_M_sequence || _M_version != _M_sequence->_M_version; }
+  { return _M_is_singular(); }
 
   bool
   _Safe_iterator_base::
   _M_can_compare(const _Safe_iterator_base& __x) const noexcept
-  { return _M_sequence == __x._M_sequence; }
+  { return _M_is_comparable(__x); }
+#endif
 
   __gnu_cxx::__mutex&
   _Safe_iterator_base::
@@ -711,7 +713,7 @@ namespace __gnu_debug
     __it->_M_unlink();
     if (_M_const_local_iterators == __it)
       _M_const_local_iterators = __it->_M_next;
-    if (_M_local_iterators == __it)
+    else if (_M_local_iterators == __it)
       _M_local_iterators = __it->_M_next;
   }
 
diff --git 
a/libstdc++-v3/testsuite/23_containers/vector/debug/consteval_erase_neg.cc 
b/libstdc++-v3/testsuite/23_containers/vector/debug/consteval_erase_neg.cc
new file mode 100644
index 00000000000..601fa08ba1d
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/debug/consteval_erase_neg.cc
@@ -0,0 +1,24 @@
+// { dg-do compile { target c++20 } }
+// { dg-require-debug-mode "" }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+constexpr bool test01()
+{
+  std::vector<int> v1, v2;
+
+  for (int i = 0; i != 10; ++i)
+    {
+      v1.push_back(i);
+      v2.push_back(i);
+    }
+
+  v1.erase(v2.begin()); // { dg-error "in 'constexpr' expansion of" }
+  return true;
+}
+
+static_assert( test01() );
+
+// { dg-prune-output "non-constant condition for static assertion" }
+// { dg-prune-output "call to non-'constexpr' function" }
diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/erase_neg.cc 
b/libstdc++-v3/testsuite/23_containers/vector/debug/erase_neg.cc
new file mode 100644
index 00000000000..ff792eca00e
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/debug/erase_neg.cc
@@ -0,0 +1,25 @@
+// { dg-do run { xfail *-*-* } }
+// { dg-require-debug-mode "" }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+bool test01()
+{
+  std::vector<int> v1, v2;
+
+  for (int i = 0; i != 10; ++i)
+    {
+      v1.push_back(i);
+      v2.push_back(i);
+    }
+
+  v1.erase(v2.begin()); // Invalid iterator.
+  return true;
+}
+
+int main()
+{
+  test01();
+  return 0;
+}

Reply via email to