[_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
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
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
>
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
> >
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
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
> >>>
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
> > >>>
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
>>>>>>
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
> >>>>>>
>
@@ -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() { }