[_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base code cleanup

Message ID 275dd157-36d2-4104-aa63-2b5871f41a0e@gmail.com
State New
Headers
Series [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base code cleanup |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed

Commit Message

François Dumont Oct. 1, 2026, 5:28 p.m. UTC
  I'd like to commit this code cleanup. It is not fixing anything except 
perhaps for some code analysis tools reporting minor issues.

Despite being trivial and limited to _GLIBCCX_DEBUG I'd like to have 
some feedback at least on the ChangeLog, to make sure I've used the 
right C++ words.

     libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base 
code cleanup

     Use inlined initialization for both _Safe_iterator_base and
     _Safe_sequence_base and so default their default constructor.

     Have _Safe_sequence_base copy constructor always defined, using same
     implementation as the default constructor.

     Use value-initialization syntax when setting pointers to nullptr 
before C++11
     instead of using 0.

     libstdc++-v3/ChangeLog:

             * include/debug/safe_base.h
             [__cplusplus >= 201103L]
             (_Safe_iterator_base::_M_sequence): Add inline initialization.
             (_Safe_iterator_base::_M_version): Likewise.
             (_Safe_iterator_base::_M_prior): Likewise.
             (_Safe_iterator_base::_M_next): Likewise.
             [__cplusplus < 201103L](_Safe_iterator_base()): Value 
initialize members.
             [__cplusplus >= 201103L](_Safe_iterator_base()): Default 
implementation.
             (_Safe_iterator_base(const _Safe_sequence_base*, bool)): 
Value initialize members.
             (_Safe_iterator_base(const _Safe_iterator_base&, bool)): 
Likewise.
             [__cplusplus >= 201103L]
             (_Safe_sequence_base::_M_iterators): Add inline initialization.
             (_Safe_sequence_base::_M_const_iterators): Likewise.
             (_Safe_sequence_base::_M_version): Likewise.
             [__cplusplus < 201103L](_Safe_sequence_base()): Value 
initialize members.
             [__cplusplus >= 201103L](_Safe_sequence_base()): Default 
implementation.
             [__cplusplus < 201103L](_Safe_sequence_base(const 
_Safe_sequence_base&)): New.

Tested under Linux x86_64 C++98 and C++20 _GLIBCXX_DEBUG mode.

Ok to commit ?

François
  

Comments

Jonathan Wakely Oct. 1, 2026, 5:36 p.m. UTC | #1
On Thu, 1 Oct 2026 at 18:29, François Dumont <frs.dumont@gmail.com> wrote:
>
> I'd like to commit this code cleanup. It is not fixing anything except
> perhaps for some code analysis tools reporting minor issues.

Does this really clean things up? Now there are two definitions for
most of those constructors.

Maybe it's possible to just use the >= 201103 versions
unconditionally, and disable -Wc++11-extensions warnings?


>
> Despite being trivial and limited to _GLIBCCX_DEBUG I'd like to have
> some feedback at least on the ChangeLog, to make sure I've used the
> right C++ words.
>
>      libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base
> code cleanup
>
>      Use inlined initialization for both _Safe_iterator_base and
>      _Safe_sequence_base and so default their default constructor.
>
>      Have _Safe_sequence_base copy constructor always defined, using same
>      implementation as the default constructor.
>
>      Use value-initialization syntax when setting pointers to nullptr
> before C++11
>      instead of using 0.
>
>      libstdc++-v3/ChangeLog:
>
>              * include/debug/safe_base.h
>              [__cplusplus >= 201103L]
>              (_Safe_iterator_base::_M_sequence): Add inline initialization.

You've added a default member-initializer

>              (_Safe_iterator_base::_M_version): Likewise.
>              (_Safe_iterator_base::_M_prior): Likewise.
>              (_Safe_iterator_base::_M_next): Likewise.
>              [__cplusplus < 201103L](_Safe_iterator_base()): Value
> initialize members.
>              [__cplusplus >= 201103L](_Safe_iterator_base()): Default
> implementation.
>              (_Safe_iterator_base(const _Safe_sequence_base*, bool)):
> Value initialize members.
>              (_Safe_iterator_base(const _Safe_iterator_base&, bool)):
> Likewise.
>              [__cplusplus >= 201103L]
>              (_Safe_sequence_base::_M_iterators): Add inline initialization.
>              (_Safe_sequence_base::_M_const_iterators): Likewise.
>              (_Safe_sequence_base::_M_version): Likewise.
>              [__cplusplus < 201103L](_Safe_sequence_base()): Value
> initialize members.
>              [__cplusplus >= 201103L](_Safe_sequence_base()): Default
> implementation.
>              [__cplusplus < 201103L](_Safe_sequence_base(const
> _Safe_sequence_base&)): New.
>
> Tested under Linux x86_64 C++98 and C++20 _GLIBCXX_DEBUG mode.
>
> Ok to commit ?
>
> François
>
  
Jonathan Wakely Oct. 1, 2026, 10:14 p.m. UTC | #2
On Thu, 1 Oct 2026 at 18:36, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On Thu, 1 Oct 2026 at 18:29, François Dumont <frs.dumont@gmail.com> wrote:
> >
> > I'd like to commit this code cleanup. It is not fixing anything except
> > perhaps for some code analysis tools reporting minor issues.
>
> Does this really clean things up? Now there are two definitions for
> most of those constructors.
>
> Maybe it's possible to just use the >= 201103 versions
> unconditionally, and disable -Wc++11-extensions warnings?

Yes, both GCC and Clang compile this without warnings using -std=c++98

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wc++11-extensions"
template<class T>
struct S
{
  S() = default;
  S(const S&) = default;

  T i = 0;
};
#pragma GCC diagnostic pop

int main()
{
  S<int> s;
}

So you can add those pragmas and then *really* clean up the code, by
only keeping the versions with the defaulted constructors and the
default member-initializers.



>
>
> >
> > Despite being trivial and limited to _GLIBCCX_DEBUG I'd like to have
> > some feedback at least on the ChangeLog, to make sure I've used the
> > right C++ words.
> >
> >      libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base
> > code cleanup
> >
> >      Use inlined initialization for both _Safe_iterator_base and
> >      _Safe_sequence_base and so default their default constructor.
> >
> >      Have _Safe_sequence_base copy constructor always defined, using same
> >      implementation as the default constructor.
> >
> >      Use value-initialization syntax when setting pointers to nullptr
> > before C++11
> >      instead of using 0.
> >
> >      libstdc++-v3/ChangeLog:
> >
> >              * include/debug/safe_base.h
> >              [__cplusplus >= 201103L]
> >              (_Safe_iterator_base::_M_sequence): Add inline initialization.
>
> You've added a default member-initializer
>
> >              (_Safe_iterator_base::_M_version): Likewise.
> >              (_Safe_iterator_base::_M_prior): Likewise.
> >              (_Safe_iterator_base::_M_next): Likewise.
> >              [__cplusplus < 201103L](_Safe_iterator_base()): Value
> > initialize members.
> >              [__cplusplus >= 201103L](_Safe_iterator_base()): Default
> > implementation.
> >              (_Safe_iterator_base(const _Safe_sequence_base*, bool)):
> > Value initialize members.
> >              (_Safe_iterator_base(const _Safe_iterator_base&, bool)):
> > Likewise.
> >              [__cplusplus >= 201103L]
> >              (_Safe_sequence_base::_M_iterators): Add inline initialization.
> >              (_Safe_sequence_base::_M_const_iterators): Likewise.
> >              (_Safe_sequence_base::_M_version): Likewise.
> >              [__cplusplus < 201103L](_Safe_sequence_base()): Value
> > initialize members.
> >              [__cplusplus >= 201103L](_Safe_sequence_base()): Default
> > implementation.
> >              [__cplusplus < 201103L](_Safe_sequence_base(const
> > _Safe_sequence_base&)): New.
> >
> > Tested under Linux x86_64 C++98 and C++20 _GLIBCXX_DEBUG mode.
> >
> > Ok to commit ?
> >
> > François
> >
  
François Dumont Oct. 5, 2026, 5:34 p.m. UTC | #3
Much better indeed.

Disabling C++11 extensions warning does not give access to 'nullptr' 
keyword so I used value-initialization, I hope it is fine.

Maybe I should also use only 1 block of #pragma GCC diagnostic push/pop 
so enclosing almost all header content within it ?

     libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base 
code cleanup

     Use default member-initializer for both _Safe_iterator_base and
     _Safe_sequence_base and so default their default constructor.

     Have _Safe_sequence_base copy constructor always defined, 
forwarding to the default constructor.

     Use value-initialization syntax when setting pointers to nullptr 
instead of
     using '= 0'.

     libstdc++-v3/ChangeLog:

             * include/debug/safe_base.h
             (_Safe_iterator_base::_M_sequence): Add default 
member-initializer.
             (_Safe_iterator_base::_M_version): Likewise.
             (_Safe_iterator_base::_M_prior): Likewise.
             (_Safe_iterator_base::_M_next): Likewise.
             (_Safe_iterator_base()): Default implementation.
             (_Safe_iterator_base(const _Safe_sequence_base*, bool)): 
Forward to default
             constructor.
             (_Safe_iterator_base(const _Safe_iterator_base&, bool)): 
Likewise.
             (_Safe_sequence_base::_M_iterators): Add default 
member-initializer.
             (_Safe_sequence_base::_M_const_iterators): Likewise.
             (_Safe_sequence_base::_M_version): Likewise.
             (_Safe_sequence_base()): Default implementation.
             (_Safe_sequence_base(const _Safe_sequence_base&)): Forward 
to default
             constructor.

Tested under Linux x86_64 _GLIBCXX_DEBUG mode C++98/C++20.

Ok to commit ?

François

On 10/2/26 00:14, Jonathan Wakely wrote:
> On Thu, 1 Oct 2026 at 18:36, Jonathan Wakely <jwakely@redhat.com> wrote:
>> On Thu, 1 Oct 2026 at 18:29, François Dumont <frs.dumont@gmail.com> wrote:
>>> I'd like to commit this code cleanup. It is not fixing anything except
>>> perhaps for some code analysis tools reporting minor issues.
>> Does this really clean things up? Now there are two definitions for
>> most of those constructors.
>>
>> Maybe it's possible to just use the >= 201103 versions
>> unconditionally, and disable -Wc++11-extensions warnings?
> Yes, both GCC and Clang compile this without warnings using -std=c++98
>
> #pragma GCC diagnostic push
> #pragma GCC diagnostic ignored "-Wc++11-extensions"
> template<class T>
> struct S
> {
>    S() = default;
>    S(const S&) = default;
>
>    T i = 0;
> };
> #pragma GCC diagnostic pop
>
> int main()
> {
>    S<int> s;
> }
>
> So you can add those pragmas and then *really* clean up the code, by
> only keeping the versions with the defaulted constructors and the
> default member-initializers.
>
>
>
>>
>>> Despite being trivial and limited to _GLIBCCX_DEBUG I'd like to have
>>> some feedback at least on the ChangeLog, to make sure I've used the
>>> right C++ words.
>>>
>>>       libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base
>>> code cleanup
>>>
>>>       Use inlined initialization for both _Safe_iterator_base and
>>>       _Safe_sequence_base and so default their default constructor.
>>>
>>>       Have _Safe_sequence_base copy constructor always defined, using same
>>>       implementation as the default constructor.
>>>
>>>       Use value-initialization syntax when setting pointers to nullptr
>>> before C++11
>>>       instead of using 0.
>>>
>>>       libstdc++-v3/ChangeLog:
>>>
>>>               * include/debug/safe_base.h
>>>               [__cplusplus >= 201103L]
>>>               (_Safe_iterator_base::_M_sequence): Add inline initialization.
>> You've added a default member-initializer
>>
>>>               (_Safe_iterator_base::_M_version): Likewise.
>>>               (_Safe_iterator_base::_M_prior): Likewise.
>>>               (_Safe_iterator_base::_M_next): Likewise.
>>>               [__cplusplus < 201103L](_Safe_iterator_base()): Value
>>> initialize members.
>>>               [__cplusplus >= 201103L](_Safe_iterator_base()): Default
>>> implementation.
>>>               (_Safe_iterator_base(const _Safe_sequence_base*, bool)):
>>> Value initialize members.
>>>               (_Safe_iterator_base(const _Safe_iterator_base&, bool)):
>>> Likewise.
>>>               [__cplusplus >= 201103L]
>>>               (_Safe_sequence_base::_M_iterators): Add inline initialization.
>>>               (_Safe_sequence_base::_M_const_iterators): Likewise.
>>>               (_Safe_sequence_base::_M_version): Likewise.
>>>               [__cplusplus < 201103L](_Safe_sequence_base()): Value
>>> initialize members.
>>>               [__cplusplus >= 201103L](_Safe_sequence_base()): Default
>>> implementation.
>>>               [__cplusplus < 201103L](_Safe_sequence_base(const
>>> _Safe_sequence_base&)): New.
>>>
>>> Tested under Linux x86_64 C++98 and C++20 _GLIBCXX_DEBUG mode.
>>>
>>> Ok to commit ?
>>>
>>> François
>>>
diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h
index 6ea499ef239..7152760129f 100644
--- a/libstdc++-v3/include/debug/safe_base.h
+++ b/libstdc++-v3/include/debug/safe_base.h
@@ -51,12 +51,14 @@ namespace __gnu_debug
   {
     friend class _Safe_sequence_base;
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++11-extensions"
   public:
     /** The sequence this iterator references; may be NULL to indicate
      *  a singular iterator. Stored as pointer-to-const because sequence
      *  could be declared as const.
      */
-    const _Safe_sequence_base*	_M_sequence;
+    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
@@ -65,22 +67,20 @@ namespace __gnu_debug
      *  referenced by _M_sequence for the iterator to be
      *  non-singular.
      */
-    unsigned int		_M_version;
+    unsigned int		_M_version = 0;
 
     /** Pointer to the previous iterator in the sequence's list of
 	iterators. Only valid when _M_sequence != NULL. */
-    _Safe_iterator_base*	_M_prior;
+    _Safe_iterator_base*	_M_prior { };
 
     /** Pointer to the next iterator in the sequence's list of
 	iterators. Only valid when _M_sequence != NULL. */
-    _Safe_iterator_base*	_M_next;
+    _Safe_iterator_base*	_M_next { };
 
   protected:
     /** Initializes the iterator and makes it singular. */
     _GLIBCXX20_CONSTEXPR
-    _Safe_iterator_base()
-    : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
-    { }
+    _Safe_iterator_base() = default;
 
     /** Initialize the iterator to reference the sequence pointed to
      *  by @p __seq. @p __constant is true when we are initializing a
@@ -91,7 +91,7 @@ namespace __gnu_debug
      */
     _GLIBCXX20_CONSTEXPR
     _Safe_iterator_base(const _Safe_sequence_base* __seq, bool __constant)
-    : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
+    : _Safe_iterator_base()
     {
       if (!std::__is_constant_evaluated())
 	this->_M_attach(__seq, __constant);
@@ -102,11 +102,12 @@ namespace __gnu_debug
 	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)
+    : _Safe_iterator_base()
     {
       if (!std::__is_constant_evaluated())
 	this->_M_attach(__x._M_sequence, __constant);
     }
+#pragma GCC diagnostic pop
 
     _GLIBCXX20_CONSTEXPR
     ~_Safe_iterator_base()
@@ -219,28 +220,29 @@ namespace __gnu_debug
   {
     friend class _Safe_iterator_base;
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++11-extensions"
   public:
     /// The list of mutable iterators that reference this container
-    mutable _Safe_iterator_base* _M_iterators;
+    mutable _Safe_iterator_base*	_M_iterators { };
 
     /// The list of constant iterators that reference this container
-    mutable _Safe_iterator_base* _M_const_iterators;
+    mutable _Safe_iterator_base*	_M_const_iterators { };
 
     /// The container version number. This number may never be 0.
-    mutable unsigned int _M_version;
+    mutable unsigned int		_M_version = 1;
 
   protected:
     // Initialize with a version number of 1 and no iterators
     _GLIBCXX20_CONSTEXPR
-    _Safe_sequence_base() _GLIBCXX_NOEXCEPT
-    : _M_iterators(0), _M_const_iterators(0), _M_version(1)
-    { }
+    _Safe_sequence_base() = default;
 
-#if __cplusplus >= 201103L
     _GLIBCXX20_CONSTEXPR
-    _Safe_sequence_base(const _Safe_sequence_base&) noexcept
+    _Safe_sequence_base(const _Safe_sequence_base&) _GLIBCXX_NOEXCEPT
     : _Safe_sequence_base() { }
+#pragma GCC diagnostic pop
 
+#if __cplusplus >= 201103L
     // Move constructor swap iterators.
     _GLIBCXX20_CONSTEXPR
     _Safe_sequence_base(_Safe_sequence_base&& __seq) noexcept
  
Jonathan Wakely Oct. 5, 2026, 5:42 p.m. UTC | #4
On Mon, 5 Oct 2026 at 18:34, François Dumont <frs.dumont@gmail.com> wrote:
>
> Much better indeed.
>
> Disabling C++11 extensions warning does not give access to 'nullptr'
> keyword so I used value-initialization, I hope it is fine.

We generally just use '= 0' to initialize pointers in C++98 code.

>
> Maybe I should also use only 1 block of #pragma GCC diagnostic push/pop
> so enclosing almost all header content within it ?

If there were many uses of it then I'd say yes, but there are only two
such blocks so this is OK.


>
>      libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base
> code cleanup
>
>      Use default member-initializer for both _Safe_iterator_base and
>      _Safe_sequence_base and so default their default constructor.
>
>      Have _Safe_sequence_base copy constructor always defined,
> forwarding to the default constructor.
>
>      Use value-initialization syntax when setting pointers to nullptr
> instead of
>      using '= 0'.

The commit log should mention that it's using C++11 features but
disabling the warnings with pragmas.


>
>      libstdc++-v3/ChangeLog:
>
>              * include/debug/safe_base.h
>              (_Safe_iterator_base::_M_sequence): Add default
> member-initializer.
>              (_Safe_iterator_base::_M_version): Likewise.
>              (_Safe_iterator_base::_M_prior): Likewise.
>              (_Safe_iterator_base::_M_next): Likewise.
>              (_Safe_iterator_base()): Default implementation.
>              (_Safe_iterator_base(const _Safe_sequence_base*, bool)):
> Forward to default
>              constructor.
>              (_Safe_iterator_base(const _Safe_iterator_base&, bool)):
> Likewise.
>              (_Safe_sequence_base::_M_iterators): Add default
> member-initializer.
>              (_Safe_sequence_base::_M_const_iterators): Likewise.
>              (_Safe_sequence_base::_M_version): Likewise.
>              (_Safe_sequence_base()): Default implementation.
>              (_Safe_sequence_base(const _Safe_sequence_base&)): Forward
> to default
>              constructor.
>
> Tested under Linux x86_64 _GLIBCXX_DEBUG mode C++98/C++20.
>
> Ok to commit ?
>
> François
>
> On 10/2/26 00:14, Jonathan Wakely wrote:
> > On Thu, 1 Oct 2026 at 18:36, Jonathan Wakely <jwakely@redhat.com> wrote:
> >> On Thu, 1 Oct 2026 at 18:29, François Dumont <frs.dumont@gmail.com> wrote:
> >>> I'd like to commit this code cleanup. It is not fixing anything except
> >>> perhaps for some code analysis tools reporting minor issues.
> >> Does this really clean things up? Now there are two definitions for
> >> most of those constructors.
> >>
> >> Maybe it's possible to just use the >= 201103 versions
> >> unconditionally, and disable -Wc++11-extensions warnings?
> > Yes, both GCC and Clang compile this without warnings using -std=c++98
> >
> > #pragma GCC diagnostic push
> > #pragma GCC diagnostic ignored "-Wc++11-extensions"
> > template<class T>
> > struct S
> > {
> >    S() = default;
> >    S(const S&) = default;
> >
> >    T i = 0;
> > };
> > #pragma GCC diagnostic pop
> >
> > int main()
> > {
> >    S<int> s;
> > }
> >
> > So you can add those pragmas and then *really* clean up the code, by
> > only keeping the versions with the defaulted constructors and the
> > default member-initializers.
> >
> >
> >
> >>
> >>> Despite being trivial and limited to _GLIBCCX_DEBUG I'd like to have
> >>> some feedback at least on the ChangeLog, to make sure I've used the
> >>> right C++ words.
> >>>
> >>>       libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base
> >>> code cleanup
> >>>
> >>>       Use inlined initialization for both _Safe_iterator_base and
> >>>       _Safe_sequence_base and so default their default constructor.
> >>>
> >>>       Have _Safe_sequence_base copy constructor always defined, using same
> >>>       implementation as the default constructor.
> >>>
> >>>       Use value-initialization syntax when setting pointers to nullptr
> >>> before C++11
> >>>       instead of using 0.
> >>>
> >>>       libstdc++-v3/ChangeLog:
> >>>
> >>>               * include/debug/safe_base.h
> >>>               [__cplusplus >= 201103L]
> >>>               (_Safe_iterator_base::_M_sequence): Add inline initialization.
> >> You've added a default member-initializer
> >>
> >>>               (_Safe_iterator_base::_M_version): Likewise.
> >>>               (_Safe_iterator_base::_M_prior): Likewise.
> >>>               (_Safe_iterator_base::_M_next): Likewise.
> >>>               [__cplusplus < 201103L](_Safe_iterator_base()): Value
> >>> initialize members.
> >>>               [__cplusplus >= 201103L](_Safe_iterator_base()): Default
> >>> implementation.
> >>>               (_Safe_iterator_base(const _Safe_sequence_base*, bool)):
> >>> Value initialize members.
> >>>               (_Safe_iterator_base(const _Safe_iterator_base&, bool)):
> >>> Likewise.
> >>>               [__cplusplus >= 201103L]
> >>>               (_Safe_sequence_base::_M_iterators): Add inline initialization.
> >>>               (_Safe_sequence_base::_M_const_iterators): Likewise.
> >>>               (_Safe_sequence_base::_M_version): Likewise.
> >>>               [__cplusplus < 201103L](_Safe_sequence_base()): Value
> >>> initialize members.
> >>>               [__cplusplus >= 201103L](_Safe_sequence_base()): Default
> >>> implementation.
> >>>               [__cplusplus < 201103L](_Safe_sequence_base(const
> >>> _Safe_sequence_base&)): New.
> >>>
> >>> Tested under Linux x86_64 C++98 and C++20 _GLIBCXX_DEBUG mode.
> >>>
> >>> Ok to commit ?
> >>>
> >>> François
> >>>
  
Jonathan Wakely Oct. 5, 2026, 5:43 p.m. UTC | #5
OK for trunk with a change to the commit log to mention it's using
C++11 extensions.

On Mon, 5 Oct 2026 at 18:42, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On Mon, 5 Oct 2026 at 18:34, François Dumont <frs.dumont@gmail.com> wrote:
> >
> > Much better indeed.
> >
> > Disabling C++11 extensions warning does not give access to 'nullptr'
> > keyword so I used value-initialization, I hope it is fine.
>
> We generally just use '= 0' to initialize pointers in C++98 code.
>
> >
> > Maybe I should also use only 1 block of #pragma GCC diagnostic push/pop
> > so enclosing almost all header content within it ?
>
> If there were many uses of it then I'd say yes, but there are only two
> such blocks so this is OK.
>
>
> >
> >      libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base
> > code cleanup
> >
> >      Use default member-initializer for both _Safe_iterator_base and
> >      _Safe_sequence_base and so default their default constructor.
> >
> >      Have _Safe_sequence_base copy constructor always defined,
> > forwarding to the default constructor.
> >
> >      Use value-initialization syntax when setting pointers to nullptr
> > instead of
> >      using '= 0'.
>
> The commit log should mention that it's using C++11 features but
> disabling the warnings with pragmas.
>
>
> >
> >      libstdc++-v3/ChangeLog:
> >
> >              * include/debug/safe_base.h
> >              (_Safe_iterator_base::_M_sequence): Add default
> > member-initializer.
> >              (_Safe_iterator_base::_M_version): Likewise.
> >              (_Safe_iterator_base::_M_prior): Likewise.
> >              (_Safe_iterator_base::_M_next): Likewise.
> >              (_Safe_iterator_base()): Default implementation.
> >              (_Safe_iterator_base(const _Safe_sequence_base*, bool)):
> > Forward to default
> >              constructor.
> >              (_Safe_iterator_base(const _Safe_iterator_base&, bool)):
> > Likewise.
> >              (_Safe_sequence_base::_M_iterators): Add default
> > member-initializer.
> >              (_Safe_sequence_base::_M_const_iterators): Likewise.
> >              (_Safe_sequence_base::_M_version): Likewise.
> >              (_Safe_sequence_base()): Default implementation.
> >              (_Safe_sequence_base(const _Safe_sequence_base&)): Forward
> > to default
> >              constructor.
> >
> > Tested under Linux x86_64 _GLIBCXX_DEBUG mode C++98/C++20.
> >
> > Ok to commit ?
> >
> > François
> >
> > On 10/2/26 00:14, Jonathan Wakely wrote:
> > > On Thu, 1 Oct 2026 at 18:36, Jonathan Wakely <jwakely@redhat.com> wrote:
> > >> On Thu, 1 Oct 2026 at 18:29, François Dumont <frs.dumont@gmail.com> wrote:
> > >>> I'd like to commit this code cleanup. It is not fixing anything except
> > >>> perhaps for some code analysis tools reporting minor issues.
> > >> Does this really clean things up? Now there are two definitions for
> > >> most of those constructors.
> > >>
> > >> Maybe it's possible to just use the >= 201103 versions
> > >> unconditionally, and disable -Wc++11-extensions warnings?
> > > Yes, both GCC and Clang compile this without warnings using -std=c++98
> > >
> > > #pragma GCC diagnostic push
> > > #pragma GCC diagnostic ignored "-Wc++11-extensions"
> > > template<class T>
> > > struct S
> > > {
> > >    S() = default;
> > >    S(const S&) = default;
> > >
> > >    T i = 0;
> > > };
> > > #pragma GCC diagnostic pop
> > >
> > > int main()
> > > {
> > >    S<int> s;
> > > }
> > >
> > > So you can add those pragmas and then *really* clean up the code, by
> > > only keeping the versions with the defaulted constructors and the
> > > default member-initializers.
> > >
> > >
> > >
> > >>
> > >>> Despite being trivial and limited to _GLIBCCX_DEBUG I'd like to have
> > >>> some feedback at least on the ChangeLog, to make sure I've used the
> > >>> right C++ words.
> > >>>
> > >>>       libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base
> > >>> code cleanup
> > >>>
> > >>>       Use inlined initialization for both _Safe_iterator_base and
> > >>>       _Safe_sequence_base and so default their default constructor.
> > >>>
> > >>>       Have _Safe_sequence_base copy constructor always defined, using same
> > >>>       implementation as the default constructor.
> > >>>
> > >>>       Use value-initialization syntax when setting pointers to nullptr
> > >>> before C++11
> > >>>       instead of using 0.
> > >>>
> > >>>       libstdc++-v3/ChangeLog:
> > >>>
> > >>>               * include/debug/safe_base.h
> > >>>               [__cplusplus >= 201103L]
> > >>>               (_Safe_iterator_base::_M_sequence): Add inline initialization.
> > >> You've added a default member-initializer
> > >>
> > >>>               (_Safe_iterator_base::_M_version): Likewise.
> > >>>               (_Safe_iterator_base::_M_prior): Likewise.
> > >>>               (_Safe_iterator_base::_M_next): Likewise.
> > >>>               [__cplusplus < 201103L](_Safe_iterator_base()): Value
> > >>> initialize members.
> > >>>               [__cplusplus >= 201103L](_Safe_iterator_base()): Default
> > >>> implementation.
> > >>>               (_Safe_iterator_base(const _Safe_sequence_base*, bool)):
> > >>> Value initialize members.
> > >>>               (_Safe_iterator_base(const _Safe_iterator_base&, bool)):
> > >>> Likewise.
> > >>>               [__cplusplus >= 201103L]
> > >>>               (_Safe_sequence_base::_M_iterators): Add inline initialization.
> > >>>               (_Safe_sequence_base::_M_const_iterators): Likewise.
> > >>>               (_Safe_sequence_base::_M_version): Likewise.
> > >>>               [__cplusplus < 201103L](_Safe_sequence_base()): Value
> > >>> initialize members.
> > >>>               [__cplusplus >= 201103L](_Safe_sequence_base()): Default
> > >>> implementation.
> > >>>               [__cplusplus < 201103L](_Safe_sequence_base(const
> > >>> _Safe_sequence_base&)): New.
> > >>>
> > >>> Tested under Linux x86_64 C++98 and C++20 _GLIBCXX_DEBUG mode.
> > >>>
> > >>> Ok to commit ?
> > >>>
> > >>> François
> > >>>
  
François Dumont Oct. 7, 2026, 4:54 a.m. UTC | #6
Committed, using '= 0' to initialize pointers.

On 10/5/26 19:43, Jonathan Wakely wrote:
> OK for trunk with a change to the commit log to mention it's using
> C++11 extensions.
>
> On Mon, 5 Oct 2026 at 18:42, Jonathan Wakely <jwakely@redhat.com> wrote:
>> On Mon, 5 Oct 2026 at 18:34, François Dumont <frs.dumont@gmail.com> wrote:
>>> Much better indeed.
>>>
>>> Disabling C++11 extensions warning does not give access to 'nullptr'
>>> keyword so I used value-initialization, I hope it is fine.
>> We generally just use '= 0' to initialize pointers in C++98 code.
>>
>>> Maybe I should also use only 1 block of #pragma GCC diagnostic push/pop
>>> so enclosing almost all header content within it ?
>> If there were many uses of it then I'd say yes, but there are only two
>> such blocks so this is OK.
>>
>>
>>>       libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base
>>> code cleanup
>>>
>>>       Use default member-initializer for both _Safe_iterator_base and
>>>       _Safe_sequence_base and so default their default constructor.
>>>
>>>       Have _Safe_sequence_base copy constructor always defined,
>>> forwarding to the default constructor.
>>>
>>>       Use value-initialization syntax when setting pointers to nullptr
>>> instead of
>>>       using '= 0'.
>> The commit log should mention that it's using C++11 features but
>> disabling the warnings with pragmas.
>>
>>
>>>       libstdc++-v3/ChangeLog:
>>>
>>>               * include/debug/safe_base.h
>>>               (_Safe_iterator_base::_M_sequence): Add default
>>> member-initializer.
>>>               (_Safe_iterator_base::_M_version): Likewise.
>>>               (_Safe_iterator_base::_M_prior): Likewise.
>>>               (_Safe_iterator_base::_M_next): Likewise.
>>>               (_Safe_iterator_base()): Default implementation.
>>>               (_Safe_iterator_base(const _Safe_sequence_base*, bool)):
>>> Forward to default
>>>               constructor.
>>>               (_Safe_iterator_base(const _Safe_iterator_base&, bool)):
>>> Likewise.
>>>               (_Safe_sequence_base::_M_iterators): Add default
>>> member-initializer.
>>>               (_Safe_sequence_base::_M_const_iterators): Likewise.
>>>               (_Safe_sequence_base::_M_version): Likewise.
>>>               (_Safe_sequence_base()): Default implementation.
>>>               (_Safe_sequence_base(const _Safe_sequence_base&)): Forward
>>> to default
>>>               constructor.
>>>
>>> Tested under Linux x86_64 _GLIBCXX_DEBUG mode C++98/C++20.
>>>
>>> Ok to commit ?
>>>
>>> François
>>>
>>> On 10/2/26 00:14, Jonathan Wakely wrote:
>>>> On Thu, 1 Oct 2026 at 18:36, Jonathan Wakely <jwakely@redhat.com> wrote:
>>>>> On Thu, 1 Oct 2026 at 18:29, François Dumont <frs.dumont@gmail.com> wrote:
>>>>>> I'd like to commit this code cleanup. It is not fixing anything except
>>>>>> perhaps for some code analysis tools reporting minor issues.
>>>>> Does this really clean things up? Now there are two definitions for
>>>>> most of those constructors.
>>>>>
>>>>> Maybe it's possible to just use the >= 201103 versions
>>>>> unconditionally, and disable -Wc++11-extensions warnings?
>>>> Yes, both GCC and Clang compile this without warnings using -std=c++98
>>>>
>>>> #pragma GCC diagnostic push
>>>> #pragma GCC diagnostic ignored "-Wc++11-extensions"
>>>> template<class T>
>>>> struct S
>>>> {
>>>>     S() = default;
>>>>     S(const S&) = default;
>>>>
>>>>     T i = 0;
>>>> };
>>>> #pragma GCC diagnostic pop
>>>>
>>>> int main()
>>>> {
>>>>     S<int> s;
>>>> }
>>>>
>>>> So you can add those pragmas and then *really* clean up the code, by
>>>> only keeping the versions with the defaulted constructors and the
>>>> default member-initializers.
>>>>
>>>>
>>>>
>>>>>> Despite being trivial and limited to _GLIBCCX_DEBUG I'd like to have
>>>>>> some feedback at least on the ChangeLog, to make sure I've used the
>>>>>> right C++ words.
>>>>>>
>>>>>>        libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base
>>>>>> code cleanup
>>>>>>
>>>>>>        Use inlined initialization for both _Safe_iterator_base and
>>>>>>        _Safe_sequence_base and so default their default constructor.
>>>>>>
>>>>>>        Have _Safe_sequence_base copy constructor always defined, using same
>>>>>>        implementation as the default constructor.
>>>>>>
>>>>>>        Use value-initialization syntax when setting pointers to nullptr
>>>>>> before C++11
>>>>>>        instead of using 0.
>>>>>>
>>>>>>        libstdc++-v3/ChangeLog:
>>>>>>
>>>>>>                * include/debug/safe_base.h
>>>>>>                [__cplusplus >= 201103L]
>>>>>>                (_Safe_iterator_base::_M_sequence): Add inline initialization.
>>>>> You've added a default member-initializer
>>>>>
>>>>>>                (_Safe_iterator_base::_M_version): Likewise.
>>>>>>                (_Safe_iterator_base::_M_prior): Likewise.
>>>>>>                (_Safe_iterator_base::_M_next): Likewise.
>>>>>>                [__cplusplus < 201103L](_Safe_iterator_base()): Value
>>>>>> initialize members.
>>>>>>                [__cplusplus >= 201103L](_Safe_iterator_base()): Default
>>>>>> implementation.
>>>>>>                (_Safe_iterator_base(const _Safe_sequence_base*, bool)):
>>>>>> Value initialize members.
>>>>>>                (_Safe_iterator_base(const _Safe_iterator_base&, bool)):
>>>>>> Likewise.
>>>>>>                [__cplusplus >= 201103L]
>>>>>>                (_Safe_sequence_base::_M_iterators): Add inline initialization.
>>>>>>                (_Safe_sequence_base::_M_const_iterators): Likewise.
>>>>>>                (_Safe_sequence_base::_M_version): Likewise.
>>>>>>                [__cplusplus < 201103L](_Safe_sequence_base()): Value
>>>>>> initialize members.
>>>>>>                [__cplusplus >= 201103L](_Safe_sequence_base()): Default
>>>>>> implementation.
>>>>>>                [__cplusplus < 201103L](_Safe_sequence_base(const
>>>>>> _Safe_sequence_base&)): New.
>>>>>>
>>>>>> Tested under Linux x86_64 C++98 and C++20 _GLIBCXX_DEBUG mode.
>>>>>>
>>>>>> Ok to commit ?
>>>>>>
>>>>>> François
>>>>>>
  
Jonathan Wakely Oct. 7, 2026, 7:59 a.m. UTC | #7
On Wed, 7 Oct 2026 at 05:54, François Dumont <frs.dumont@gmail.com> wrote:
>
> Committed, using '= 0' to initialize pointers.

Thanks!

>
> On 10/5/26 19:43, Jonathan Wakely wrote:
> > OK for trunk with a change to the commit log to mention it's using
> > C++11 extensions.
> >
> > On Mon, 5 Oct 2026 at 18:42, Jonathan Wakely <jwakely@redhat.com> wrote:
> >> On Mon, 5 Oct 2026 at 18:34, François Dumont <frs.dumont@gmail.com> wrote:
> >>> Much better indeed.
> >>>
> >>> Disabling C++11 extensions warning does not give access to 'nullptr'
> >>> keyword so I used value-initialization, I hope it is fine.
> >> We generally just use '= 0' to initialize pointers in C++98 code.
> >>
> >>> Maybe I should also use only 1 block of #pragma GCC diagnostic push/pop
> >>> so enclosing almost all header content within it ?
> >> If there were many uses of it then I'd say yes, but there are only two
> >> such blocks so this is OK.
> >>
> >>
> >>>       libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base
> >>> code cleanup
> >>>
> >>>       Use default member-initializer for both _Safe_iterator_base and
> >>>       _Safe_sequence_base and so default their default constructor.
> >>>
> >>>       Have _Safe_sequence_base copy constructor always defined,
> >>> forwarding to the default constructor.
> >>>
> >>>       Use value-initialization syntax when setting pointers to nullptr
> >>> instead of
> >>>       using '= 0'.
> >> The commit log should mention that it's using C++11 features but
> >> disabling the warnings with pragmas.
> >>
> >>
> >>>       libstdc++-v3/ChangeLog:
> >>>
> >>>               * include/debug/safe_base.h
> >>>               (_Safe_iterator_base::_M_sequence): Add default
> >>> member-initializer.
> >>>               (_Safe_iterator_base::_M_version): Likewise.
> >>>               (_Safe_iterator_base::_M_prior): Likewise.
> >>>               (_Safe_iterator_base::_M_next): Likewise.
> >>>               (_Safe_iterator_base()): Default implementation.
> >>>               (_Safe_iterator_base(const _Safe_sequence_base*, bool)):
> >>> Forward to default
> >>>               constructor.
> >>>               (_Safe_iterator_base(const _Safe_iterator_base&, bool)):
> >>> Likewise.
> >>>               (_Safe_sequence_base::_M_iterators): Add default
> >>> member-initializer.
> >>>               (_Safe_sequence_base::_M_const_iterators): Likewise.
> >>>               (_Safe_sequence_base::_M_version): Likewise.
> >>>               (_Safe_sequence_base()): Default implementation.
> >>>               (_Safe_sequence_base(const _Safe_sequence_base&)): Forward
> >>> to default
> >>>               constructor.
> >>>
> >>> Tested under Linux x86_64 _GLIBCXX_DEBUG mode C++98/C++20.
> >>>
> >>> Ok to commit ?
> >>>
> >>> François
> >>>
> >>> On 10/2/26 00:14, Jonathan Wakely wrote:
> >>>> On Thu, 1 Oct 2026 at 18:36, Jonathan Wakely <jwakely@redhat.com> wrote:
> >>>>> On Thu, 1 Oct 2026 at 18:29, François Dumont <frs.dumont@gmail.com> wrote:
> >>>>>> I'd like to commit this code cleanup. It is not fixing anything except
> >>>>>> perhaps for some code analysis tools reporting minor issues.
> >>>>> Does this really clean things up? Now there are two definitions for
> >>>>> most of those constructors.
> >>>>>
> >>>>> Maybe it's possible to just use the >= 201103 versions
> >>>>> unconditionally, and disable -Wc++11-extensions warnings?
> >>>> Yes, both GCC and Clang compile this without warnings using -std=c++98
> >>>>
> >>>> #pragma GCC diagnostic push
> >>>> #pragma GCC diagnostic ignored "-Wc++11-extensions"
> >>>> template<class T>
> >>>> struct S
> >>>> {
> >>>>     S() = default;
> >>>>     S(const S&) = default;
> >>>>
> >>>>     T i = 0;
> >>>> };
> >>>> #pragma GCC diagnostic pop
> >>>>
> >>>> int main()
> >>>> {
> >>>>     S<int> s;
> >>>> }
> >>>>
> >>>> So you can add those pragmas and then *really* clean up the code, by
> >>>> only keeping the versions with the defaulted constructors and the
> >>>> default member-initializers.
> >>>>
> >>>>
> >>>>
> >>>>>> Despite being trivial and limited to _GLIBCCX_DEBUG I'd like to have
> >>>>>> some feedback at least on the ChangeLog, to make sure I've used the
> >>>>>> right C++ words.
> >>>>>>
> >>>>>>        libstdc++: [_GLIBCXX_DEBUG] _Safe_iterator_base/_Safe_sequence_base
> >>>>>> code cleanup
> >>>>>>
> >>>>>>        Use inlined initialization for both _Safe_iterator_base and
> >>>>>>        _Safe_sequence_base and so default their default constructor.
> >>>>>>
> >>>>>>        Have _Safe_sequence_base copy constructor always defined, using same
> >>>>>>        implementation as the default constructor.
> >>>>>>
> >>>>>>        Use value-initialization syntax when setting pointers to nullptr
> >>>>>> before C++11
> >>>>>>        instead of using 0.
> >>>>>>
> >>>>>>        libstdc++-v3/ChangeLog:
> >>>>>>
> >>>>>>                * include/debug/safe_base.h
> >>>>>>                [__cplusplus >= 201103L]
> >>>>>>                (_Safe_iterator_base::_M_sequence): Add inline initialization.
> >>>>> You've added a default member-initializer
> >>>>>
> >>>>>>                (_Safe_iterator_base::_M_version): Likewise.
> >>>>>>                (_Safe_iterator_base::_M_prior): Likewise.
> >>>>>>                (_Safe_iterator_base::_M_next): Likewise.
> >>>>>>                [__cplusplus < 201103L](_Safe_iterator_base()): Value
> >>>>>> initialize members.
> >>>>>>                [__cplusplus >= 201103L](_Safe_iterator_base()): Default
> >>>>>> implementation.
> >>>>>>                (_Safe_iterator_base(const _Safe_sequence_base*, bool)):
> >>>>>> Value initialize members.
> >>>>>>                (_Safe_iterator_base(const _Safe_iterator_base&, bool)):
> >>>>>> Likewise.
> >>>>>>                [__cplusplus >= 201103L]
> >>>>>>                (_Safe_sequence_base::_M_iterators): Add inline initialization.
> >>>>>>                (_Safe_sequence_base::_M_const_iterators): Likewise.
> >>>>>>                (_Safe_sequence_base::_M_version): Likewise.
> >>>>>>                [__cplusplus < 201103L](_Safe_sequence_base()): Value
> >>>>>> initialize members.
> >>>>>>                [__cplusplus >= 201103L](_Safe_sequence_base()): Default
> >>>>>> implementation.
> >>>>>>                [__cplusplus < 201103L](_Safe_sequence_base(const
> >>>>>> _Safe_sequence_base&)): New.
> >>>>>>
> >>>>>> Tested under Linux x86_64 C++98 and C++20 _GLIBCXX_DEBUG mode.
> >>>>>>
> >>>>>> Ok to commit ?
> >>>>>>
> >>>>>> François
> >>>>>>
>
  

Patch

diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h
index 6ea499ef239..d188fd6e968 100644
--- a/libstdc++-v3/include/debug/safe_base.h
+++ b/libstdc++-v3/include/debug/safe_base.h
@@ -56,7 +56,12 @@  namespace __gnu_debug
      *  a singular iterator. Stored as pointer-to-const because sequence
      *  could be declared as const.
      */
-    const _Safe_sequence_base*	_M_sequence;
+    const _Safe_sequence_base*
+#if __cplusplus < 201103L
+				_M_sequence;
+#else
+				_M_sequence = nullptr;
+#endif
 
     /** The version number of this iterator. The sentinel value 0 is
      *  used to indicate an invalidated iterator (i.e., one that is
@@ -65,22 +70,41 @@  namespace __gnu_debug
      *  referenced by _M_sequence for the iterator to be
      *  non-singular.
      */
-    unsigned int		_M_version;
+    unsigned int
+#if __cplusplus < 201103L
+				_M_version;
+#else
+				_M_version = 0;
+#endif
 
     /** Pointer to the previous iterator in the sequence's list of
 	iterators. Only valid when _M_sequence != NULL. */
-    _Safe_iterator_base*	_M_prior;
+    _Safe_iterator_base*
+#if __cplusplus < 201103L
+				_M_prior;
+#else
+				_M_prior = nullptr;
+#endif
 
     /** Pointer to the next iterator in the sequence's list of
 	iterators. Only valid when _M_sequence != NULL. */
-    _Safe_iterator_base*	_M_next;
+    _Safe_iterator_base*
+#if __cplusplus < 201103L
+				_M_next;
+#else
+				_M_next = nullptr;
+#endif
 
   protected:
     /** Initializes the iterator and makes it singular. */
     _GLIBCXX20_CONSTEXPR
     _Safe_iterator_base()
-    : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
+#if __cplusplus < 201103L
+    : _M_sequence(), _M_version(), _M_prior(), _M_next()
     { }
+#else
+    = default;
+#endif
 
     /** Initialize the iterator to reference the sequence pointed to
      *  by @p __seq. @p __constant is true when we are initializing a
@@ -91,7 +115,7 @@  namespace __gnu_debug
      */
     _GLIBCXX20_CONSTEXPR
     _Safe_iterator_base(const _Safe_sequence_base* __seq, bool __constant)
-    : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0)
+    : _M_sequence(), _M_version(), _M_prior(), _M_next()
     {
       if (!std::__is_constant_evaluated())
 	this->_M_attach(__seq, __constant);
@@ -102,7 +126,7 @@  namespace __gnu_debug
 	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)
+    : _M_sequence(), _M_version(), _M_prior(), _M_next()
     {
       if (!std::__is_constant_evaluated())
 	this->_M_attach(__x._M_sequence, __constant);
@@ -221,22 +245,45 @@  namespace __gnu_debug
 
   public:
     /// The list of mutable iterators that reference this container
-    mutable _Safe_iterator_base* _M_iterators;
+    mutable _Safe_iterator_base*
+#if __cplusplus < 201103L
+					_M_iterators;
+#else
+					_M_iterators = nullptr;
+#endif
 
     /// The list of constant iterators that reference this container
-    mutable _Safe_iterator_base* _M_const_iterators;
+    mutable _Safe_iterator_base*
+#if __cplusplus < 201103L
+					_M_const_iterators;
+#else
+					_M_const_iterators = nullptr;
+#endif
 
     /// The container version number. This number may never be 0.
-    mutable unsigned int _M_version;
+    mutable unsigned int
+#if __cplusplus < 201103L
+					_M_version;
+#else
+					_M_version = 1;
+#endif
 
   protected:
     // Initialize with a version number of 1 and no iterators
     _GLIBCXX20_CONSTEXPR
-    _Safe_sequence_base() _GLIBCXX_NOEXCEPT
-    : _M_iterators(0), _M_const_iterators(0), _M_version(1)
+    _Safe_sequence_base()
+#if __cplusplus < 201103L
+    : _M_iterators(), _M_const_iterators(), _M_version(1)
     { }
+#else
+    = default;
+#endif
 
-#if __cplusplus >= 201103L
+#if __cplusplus < 201103L
+    _Safe_sequence_base(const _Safe_sequence_base&)
+    : _M_iterators(), _M_const_iterators(), _M_version(1)
+    { }
+#else
     _GLIBCXX20_CONSTEXPR
     _Safe_sequence_base(const _Safe_sequence_base&) noexcept
     : _Safe_sequence_base() { }