On 2026/05/14 04:25, Jonathan Wakely wrote:
On Wed, 13 May 2026 at 15:29, Patrick Palka <[email protected]> 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 <[email protected]>
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 <[email protected]>
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






Reply via email to