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`

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