[PATCH] libstdc++: replace assert with __glibcxx_assert (PR libstdc++/125228)
Dragon Archer
dragon-archer@outlook.com
Thu May 14 07:14:49 GMT 2026
On 2026/05/14 04:25, Jonathan Wakely wrote:
> On Wed, 13 May 2026 at 15:29, Patrick Palka <ppalka@redhat.com> wrote:
>>
>> On Fri, 8 May 2026, Dragon Archer wrote:
>>
>>> PR libstdc++/125228
>>>
>>> This patch replaces the uses of `assert` in ryu and debug.cc with
>>> `__glibcxx_assert`, and removed their direct dependency on `<cassert>`.
>>> To avoid modifying the third-party ryu headers, this patch use
>>> `#pragma push_macro` / `#pragma pop_macro` to locally
>>> redefine `assert` to `__glibcxx_assert` when including the ryu headers.
>>>
>>> libstdc++-v3/ChangeLog:
>>>
>>> PR libstdc++/125228
>>> * src/c++11/debug.cc: Replace assert with __glibcxx_assert,
>>> and remove the include of <cassert>.
>>> * src/c++17/floating_to_chars.cc: Likewise, but redefine
>>> assert as __glibcxx_assert using pragma push/pop_macro.
>>>
>>> --
>>>
>>> From 76f866652f9a7e2fc4faf012f6b356e9a85ecb8d Mon Sep 17 00:00:00 2001
>>> From: dragon-archer <dragon-archer@outlook.com>
>>> Date: Fri, 8 May 2026 19:14:49 +0800
>>> Subject: [PATCH] libstdc++: Use __glibcxx_assert instead of assert
>>>
>>> Unlike `__glibcxx_assert` which is guarded
>>> by `_GLIBCXX_ASSERTIONS` and enabled only in Debug
>>> build of libstdc++, `assert` is either always enabled, or
>>> always disabled if manually defining `NDEBUG` before
>>> `#include <cassert>` or `#include <assert.h>`. This not
>>> only makes `assert` inflexible, but also introduces extra
>>> runtime overhead and/or increased binary size in Release
>>> builds.
>>>
>>> Uses of `assert` without `NDEBUG` introduces `__FILE__`
>>> into the final library, and can be easily found using
>>> `string`
>>
>> Seems reasonable to me (though pragma push/pop_macro don't seem strictly
>> necessary as Jonathan pointed out).
>
> I'm a little concerned that the use of the push/pop_macro pragmas
> gives the impression that we do expect 'assert' to be used elsewhere
> in that file, which isn't true.
>
> I think it would be sufficient and express the intent better to do:
>
> #define assert __glibcxx_assert
> ... include the ryu files ...
> #undef assert
>
> If for some reason assert has already been defined at that point,
> we'll get "warning: 'assert' redefined" to tell us something
> unexpected is happening, and we can investigate.
>
Sounds reasonable. I'v updated the patch below and adopt this change.
---
From 7bcd2dcb248e22908cafa01bb412c7f3bad9bba2 Mon Sep 17 00:00:00 2001
From: dragon-archer <dragon-archer@outlook.com>
Date: Fri, 8 May 2026 19:14:49 +0800
Subject: [PATCH] libstdc++: use __glibcxx_assert instead of assert
[PR125228]
This patch replaces the uses of `assert` in ryu and debug.cc with
`__glibcxx_assert`, and removed their direct dependency on `<cassert>`.
To avoid modifying the third-party ryu headers, this patch define
`assert` to `__glibcxx_assert` when including the ryu headers.
libstdc++-v3/ChangeLog:
PR libstdc++/125228
* src/c++11/debug.cc: Replace assert with __glibcxx_assert,
and remove the include of <cassert>.
* src/c++17/floating_to_chars.cc: Likewise, but define assert
as __glibcxx_assert to avoid modifying the ryu headers.
---
libstdc++-v3/src/c++11/debug.cc | 33 ++++++++++-----------
libstdc++-v3/src/c++17/floating_to_chars.cc | 3 +-
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/libstdc++-v3/src/c++11/debug.cc
b/libstdc++-v3/src/c++11/debug.cc
index 7049d5f1238..9a36bdfabb9 100644
--- a/libstdc++-v3/src/c++11/debug.cc
+++ b/libstdc++-v3/src/c++11/debug.cc
@@ -33,7 +33,6 @@
#include <debug/safe_local_iterator.h>
#include <debug/vector>
-#include <cassert>
#include <cstdio> // for std::fprintf, stderr
#include <cstdlib> // for std::abort
#include <cctype> // for std::isspace.
@@ -888,7 +887,7 @@ namespace
void
print_named_name(PrintContext& ctx, const _Parameter::_Named& named)
{
- assert(named._M_name);
+ __glibcxx_assert(named._M_name);
pretty_print(ctx, named._M_name, print_word);
}
@@ -985,7 +984,7 @@ namespace
print_iterator_state(ctx, iterator);
else if (__builtin_strcmp(fname, "sequence") == 0)
{
- assert(iterator._M_sequence);
+ __glibcxx_assert(iterator._M_sequence);
print_address(ctx, iterator._M_sequence);
}
else if (__builtin_strcmp(fname, "seq_type") == 0)
@@ -999,43 +998,43 @@ namespace
void
print_field(PrintContext& ctx, const _Parameter& param, const char*
fname)
{
- assert(param._M_kind != _Parameter::__unused_param);
+ __glibcxx_assert(param._M_kind != _Parameter::__unused_param);
const auto& variant = param._M_variant;
switch (param._M_kind)
{
case _Parameter::__iterator:
if (!print_iterator_field(ctx, fname, variant._M_iterator))
- assert(false);
+ __glibcxx_assert(false);
break;
case _Parameter::__sequence:
if (!print_instance_field(ctx, fname, variant._M_sequence))
- assert(false);
+ __glibcxx_assert(false);
break;
case _Parameter::__integer:
if (!print_named_field(ctx, fname, variant._M_integer))
- assert(false);
+ __glibcxx_assert(false);
break;
case _Parameter::__string:
if (!print_named_field(ctx, fname, variant._M_string))
- assert(false);
+ __glibcxx_assert(false);
break;
case _Parameter::__instance:
if (!print_instance_field(ctx, fname, variant._M_instance))
- assert(false);
+ __glibcxx_assert(false);
break;
case _Parameter::__iterator_value_type:
if (!print_type_field(ctx, fname, variant._M_iterator_value_type))
- assert(false);
+ __glibcxx_assert(false);
break;
default:
- assert(false);
+ __glibcxx_assert(false);
break;
}
}
@@ -1198,9 +1197,9 @@ namespace
}
// Get the parameter number
- assert(*str >= '1' && *str <= '9');
+ __glibcxx_assert(*str >= '1' && *str <= '9');
size_t param_index = *str - '0' - 1;
- assert(param_index < num_parameters);
+ __glibcxx_assert(param_index < num_parameters);
const auto& param = parameters[param_index];
// '.' separates the parameter number from the field
@@ -1208,7 +1207,7 @@ namespace
++str;
if (*str != '.')
{
- assert(*str == ';');
+ __glibcxx_assert(*str == ';');
++str;
if (param._M_kind == _Parameter::__integer)
print_integer(ctx, param._M_variant._M_integer._M_value);
@@ -1226,8 +1225,8 @@ namespace
++str;
while (*str != ';')
{
- assert(*str);
- assert(field_idx < max_field_len - 1);
+ __glibcxx_assert(*str);
+ __glibcxx_assert(field_idx < max_field_len - 1);
field[field_idx++] = *str++;
}
++str;
@@ -1382,7 +1381,7 @@ namespace __gnu_debug
print_literal(ctx, "Error: ");
// Print the error message
- assert(_M_text);
+ __glibcxx_assert(_M_text);
print_string(ctx, _M_text, -1, _M_parameters, _M_num_parameters);
print_literal(ctx, ".\n");
diff --git a/libstdc++-v3/src/c++17/floating_to_chars.cc
b/libstdc++-v3/src/c++17/floating_to_chars.cc
index 9bddffd70ff..c5dce2177e3 100644
--- a/libstdc++-v3/src/c++17/floating_to_chars.cc
+++ b/libstdc++-v3/src/c++17/floating_to_chars.cc
@@ -26,7 +26,6 @@
#include <bit>
#include <cfenv>
-#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
@@ -106,6 +105,7 @@ namespace
namespace ryu
{
+#define assert __glibcxx_assert
#include "ryu/common.h"
#include "ryu/digit_table.h"
#include "ryu/d2s_intrinsics.h"
@@ -123,6 +123,7 @@ namespace
# include "ryu/ryu_generic_128.h"
# include "ryu/generic_128.c"
} // namespace generic128
+#undef assert
using generic128::floating_decimal_128;
using generic128::generic_binary_to_decimal;
--
2.54.0.windows.1
>
>>
>> Though in theory I guess there's a risk of a performance regression by
>> removing an assert in Ryu, if the compiler relies on an assert condition
>> to be true in order to safely apply an important optimization.
>>
>> Just wondering, is there a legit problem/concern with __FILE__ appearing
>> in the final library or is it a matter of QoI (which I agree with)?
>>
>>>
>>> This is a long standing issue, dating from at least GCC
>>> 8.5.0 to latest GCC 16.1.0
>>> ---
>>> libstdc++-v3/src/c++11/debug.cc | 33 ++++++++++-----------
>>> libstdc++-v3/src/c++17/floating_to_chars.cc | 5 +++-
>>> 2 files changed, 20 insertions(+), 18 deletions(-)
>>>
>>> diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc
>>> index 7049d5f1238..9a36bdfabb9 100644
>>> --- a/libstdc++-v3/src/c++11/debug.cc
>>> +++ b/libstdc++-v3/src/c++11/debug.cc
>>> @@ -33,7 +33,6 @@
>>> #include <debug/safe_local_iterator.h>
>>> #include <debug/vector>
>>>
>>> -#include <cassert>
>>> #include <cstdio> // for std::fprintf, stderr
>>> #include <cstdlib> // for std::abort
>>> #include <cctype> // for std::isspace.
>>> @@ -888,7 +887,7 @@ namespace
>>> void
>>> print_named_name(PrintContext& ctx, const _Parameter::_Named& named)
>>> {
>>> - assert(named._M_name);
>>> + __glibcxx_assert(named._M_name);
>>> pretty_print(ctx, named._M_name, print_word);
>>> }
>>>
>>> @@ -985,7 +984,7 @@ namespace
>>> print_iterator_state(ctx, iterator);
>>> else if (__builtin_strcmp(fname, "sequence") == 0)
>>> {
>>> - assert(iterator._M_sequence);
>>> + __glibcxx_assert(iterator._M_sequence);
>>> print_address(ctx, iterator._M_sequence);
>>> }
>>> else if (__builtin_strcmp(fname, "seq_type") == 0)
>>> @@ -999,43 +998,43 @@ namespace
>>> void
>>> print_field(PrintContext& ctx, const _Parameter& param, const char* fname)
>>> {
>>> - assert(param._M_kind != _Parameter::__unused_param);
>>> + __glibcxx_assert(param._M_kind != _Parameter::__unused_param);
>>>
>>> const auto& variant = param._M_variant;
>>> switch (param._M_kind)
>>> {
>>> case _Parameter::__iterator:
>>> if (!print_iterator_field(ctx, fname, variant._M_iterator))
>>> - assert(false);
>>> + __glibcxx_assert(false);
>>> break;
>>>
>>> case _Parameter::__sequence:
>>> if (!print_instance_field(ctx, fname, variant._M_sequence))
>>> - assert(false);
>>> + __glibcxx_assert(false);
>>> break;
>>>
>>> case _Parameter::__integer:
>>> if (!print_named_field(ctx, fname, variant._M_integer))
>>> - assert(false);
>>> + __glibcxx_assert(false);
>>> break;
>>>
>>> case _Parameter::__string:
>>> if (!print_named_field(ctx, fname, variant._M_string))
>>> - assert(false);
>>> + __glibcxx_assert(false);
>>> break;
>>>
>>> case _Parameter::__instance:
>>> if (!print_instance_field(ctx, fname, variant._M_instance))
>>> - assert(false);
>>> + __glibcxx_assert(false);
>>> break;
>>>
>>> case _Parameter::__iterator_value_type:
>>> if (!print_type_field(ctx, fname, variant._M_iterator_value_type))
>>> - assert(false);
>>> + __glibcxx_assert(false);
>>> break;
>>>
>>> default:
>>> - assert(false);
>>> + __glibcxx_assert(false);
>>> break;
>>> }
>>> }
>>> @@ -1198,9 +1197,9 @@ namespace
>>> }
>>>
>>> // Get the parameter number
>>> - assert(*str >= '1' && *str <= '9');
>>> + __glibcxx_assert(*str >= '1' && *str <= '9');
>>> size_t param_index = *str - '0' - 1;
>>> - assert(param_index < num_parameters);
>>> + __glibcxx_assert(param_index < num_parameters);
>>> const auto& param = parameters[param_index];
>>>
>>> // '.' separates the parameter number from the field
>>> @@ -1208,7 +1207,7 @@ namespace
>>> ++str;
>>> if (*str != '.')
>>> {
>>> - assert(*str == ';');
>>> + __glibcxx_assert(*str == ';');
>>> ++str;
>>> if (param._M_kind == _Parameter::__integer)
>>> print_integer(ctx, param._M_variant._M_integer._M_value);
>>> @@ -1226,8 +1225,8 @@ namespace
>>> ++str;
>>> while (*str != ';')
>>> {
>>> - assert(*str);
>>> - assert(field_idx < max_field_len - 1);
>>> + __glibcxx_assert(*str);
>>> + __glibcxx_assert(field_idx < max_field_len - 1);
>>> field[field_idx++] = *str++;
>>> }
>>> ++str;
>>> @@ -1382,7 +1381,7 @@ namespace __gnu_debug
>>> print_literal(ctx, "Error: ");
>>>
>>> // Print the error message
>>> - assert(_M_text);
>>> + __glibcxx_assert(_M_text);
>>> print_string(ctx, _M_text, -1, _M_parameters, _M_num_parameters);
>>> print_literal(ctx, ".\n");
>>>
>>> diff --git a/libstdc++-v3/src/c++17/floating_to_chars.cc b/libstdc++-v3/src/c++17/floating_to_chars.cc
>>> index 9bddffd70ff..264e520e187 100644
>>> --- a/libstdc++-v3/src/c++17/floating_to_chars.cc
>>> +++ b/libstdc++-v3/src/c++17/floating_to_chars.cc
>>> @@ -26,7 +26,6 @@
>>>
>>> #include <bit>
>>> #include <cfenv>
>>> -#include <cassert>
>>> #include <cmath>
>>> #include <cstdio>
>>> #include <cstring>
>>> @@ -106,6 +105,9 @@ namespace
>>>
>>> namespace ryu
>>> {
>>> +#pragma push_macro("assert")
>>> +#undef assert
>>> +#define assert __glibcxx_assert
>>> #include "ryu/common.h"
>>> #include "ryu/digit_table.h"
>>> #include "ryu/d2s_intrinsics.h"
>>> @@ -123,6 +125,7 @@ namespace
>>> # include "ryu/ryu_generic_128.h"
>>> # include "ryu/generic_128.c"
>>> } // namespace generic128
>>> +#pragma pop_macro("assert")
>>>
>>> using generic128::floating_decimal_128;
>>> using generic128::generic_binary_to_decimal;
>>> --
>>> 2.54.0.windows.1
>>>
>>>
>>>
>>
>
More information about the Libstdc++
mailing list