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 <[email protected]> wrote:
On Thu, 1 Oct 2026 at 18:29, François Dumont <[email protected]> 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