public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] libstdc++: Rework std::format support for wchar_t
@ 2023-08-17 20:31 Jonathan Wakely
  2023-08-18  8:44 ` [committed] libstdc++: Fix incomplete rework of wchar_t support in std::format Jonathan Wakely
  0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Wakely @ 2023-08-17 20:31 UTC (permalink / raw)
  To: libstdc++, gcc-patches

Tested x86_64-linux. Pushed to trunk.

-- >8 --

This changes how std::format creates wide strings, by replacing uses of
std::ctype<wchar_t>::widen with the recently-added __to_wstring_numeric
helper function. This removes the dependency on the locale, which should
only be used for locale-specific formats such as {:Ld}.

Also disable all the wide string formatting support if the
_GLIBCXX_USE_WCHAR_T macro is not defined. This is consistent with other
wchar_t support being disabled if the library is built without that
macro defined.

libstdc++-v3/ChangeLog:

	* include/std/format [_GLIBCXX_USE_WCHAR_T]: Guard all wide
	string formatters with this macro.
	(__formatter_int::_M_format_int, __formatter_fp::format)
	(formatter<const void*, C>::format): Use __to_wstring_numeric
	instead of std::ctype::widen.
	(__formatter_fp::_M_localize): Use hardcoded wchar_t values
	instead of std::ctype::widen.
	* testsuite/std/format/functions/format.cc: Add more checks for
	wstring formatting of arithmetic types.
---
 libstdc++-v3/include/std/format               | 108 ++++++++++++------
 .../testsuite/std/format/functions/format.cc  |  10 ++
 2 files changed, 82 insertions(+), 36 deletions(-)

diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 0d7d3d16420..79f810acce3 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -79,8 +79,10 @@ namespace __format
 
   using format_context
     = basic_format_context<__format::_Sink_iter<char>, char>;
+#ifdef _GLIBCXX_USE_WCHAR_T
   using wformat_context
     = basic_format_context<__format::_Sink_iter<wchar_t>, wchar_t>;
+#endif
 
   // [format.args], class template basic_format_args
   template<typename _Context> class basic_format_args;
@@ -118,9 +120,11 @@ namespace __format
   template<typename... _Args>
     using format_string = basic_format_string<char, type_identity_t<_Args>...>;
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename... _Args>
     using wformat_string
       = basic_format_string<wchar_t, type_identity_t<_Args>...>;
+#endif
 
   // [format.formatter], formatter
 
@@ -181,7 +185,9 @@ namespace __format
   // [format.parse.ctx], class template basic_format_parse_context
   template<typename _CharT> class basic_format_parse_context;
   using format_parse_context = basic_format_parse_context<char>;
+#ifdef _GLIBCXX_USE_WCHAR_T
   using wformat_parse_context = basic_format_parse_context<wchar_t>;
+#endif
 
   template<typename _CharT>
     class basic_format_parse_context
@@ -745,8 +751,13 @@ namespace __format
     bool _M_hasval = false;
   };
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename _CharT>
     concept __char = same_as<_CharT, char> || same_as<_CharT, wchar_t>;
+#else
+  template<typename _CharT>
+    concept __char = same_as<_CharT, char>;
+#endif
 
   template<__char _CharT>
     struct __formatter_str
@@ -1125,26 +1136,20 @@ namespace __format
 	{
 	  size_t __width = _M_spec._M_get_width(__fc);
 
-	  _Optional_locale __loc;
-
 	  basic_string_view<_CharT> __str;
 	  if constexpr (is_same_v<char, _CharT>)
 	    __str = __narrow_str;
 	  else
 	    {
-	      __loc = __fc.locale();
-	      auto& __ct = use_facet<ctype<_CharT>>(__loc.value());
 	      size_t __n = __narrow_str.size();
 	      auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
-	      __ct.widen(__narrow_str.data(), __narrow_str.data() + __n, __p);
+	      __to_wstring_numeric(__narrow_str.data(), __n, __p);
 	      __str = {__p, __n};
 	    }
 
 	  if (_M_spec._M_localized)
 	    {
-	      if constexpr (is_same_v<char, _CharT>)
-		__loc = __fc.locale();
-	      const auto& __l = __loc.value();
+	      const auto& __l = __fc.locale();
 	      if (__l.name() != "C")
 		{
 		  auto& __np = use_facet<numpunct<_CharT>>(__l);
@@ -1612,35 +1617,19 @@ namespace __format
 		}
 	    }
 
-	  // TODO move everything below to a new member function that
-	  // doesn't depend on _Fp type.
-
-
-	  _Optional_locale __loc;
 	  basic_string<_CharT> __wstr;
 	  basic_string_view<_CharT> __str;
 	  if constexpr (is_same_v<_CharT, char>)
 	    __str = __narrow_str;
 	  else
 	    {
-	      __loc = __fc.locale();
-	      auto& __ct = use_facet<ctype<_CharT>>(__loc.value());
-	      const char* __data = __narrow_str.data();
-	      auto __overwrite = [&__data, &__ct](_CharT* __p, size_t __n)
-	      {
-		__ct.widen(__data, __data + __n, __p);
-		return __n;
-	      };
-	      _S_resize_and_overwrite(__wstr, __narrow_str.size(), __overwrite);
+	      __wstr = std::__to_wstring_numeric(__narrow_str);
 	      __str = __wstr;
 	    }
 
 	  if (_M_spec._M_localized)
 	    {
-	      if constexpr (is_same_v<char, _CharT>)
-		__wstr = _M_localize(__str, __expc, __fc.locale());
-	      else
-		__wstr = _M_localize(__str, __expc, __loc.value());
+	      __wstr = _M_localize(__str, __expc, __fc.locale());
 	      if (!__wstr.empty())
 		__str = __wstr;
 	    }
@@ -1697,9 +1686,24 @@ namespace __format
 	  }
 	else
 	  {
-	    const auto& __ct = use_facet<ctype<_CharT>>(__loc);
-	    __dot = __ct.widen('.');
-	    __exp = __ct.widen(__expc);
+	    __dot = L'.';
+	    switch (__expc)
+	    {
+	      case 'e':
+		__exp = L'e';
+		break;
+	      case 'E':
+		__exp = L'E';
+		break;
+	      case 'p':
+		__exp = L'p';
+		break;
+	      case 'P':
+		__exp = L'P';
+		break;
+	      default:
+		__builtin_unreachable();
+	    }
 	  }
 
 	if (__grp.empty() && __point == __dot)
@@ -1737,7 +1741,7 @@ namespace __format
 } // namespace __format
 /// @endcond
 
-  // Format a character.
+  /// Format a character.
   template<__format::__char _CharT>
     struct formatter<_CharT, _CharT>
     {
@@ -1774,7 +1778,8 @@ namespace __format
       __format::__formatter_int<_CharT> _M_f;
     };
 
-  // Format a char value for wide character output.
+#ifdef _GLIBCXX_USE_WCHAR_T
+  /// Format a char value for wide character output.
   template<>
     struct formatter<char, wchar_t>
     {
@@ -1808,6 +1813,7 @@ namespace __format
     private:
       __format::__formatter_int<wchar_t> _M_f;
     };
+#endif // USE_WCHAR_T
 
   /** Format a string.
    * @{
@@ -1903,6 +1909,7 @@ namespace __format
       __format::__formatter_str<char> _M_f;
     };
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename _Traits, typename _Alloc>
     struct formatter<basic_string<wchar_t, _Traits, _Alloc>, wchar_t>
     {
@@ -1926,6 +1933,7 @@ namespace __format
     private:
       __format::__formatter_str<wchar_t> _M_f;
     };
+#endif // USE_WCHAR_T
 
   template<typename _Traits>
     struct formatter<basic_string_view<char, _Traits>, char>
@@ -1951,6 +1959,7 @@ namespace __format
       __format::__formatter_str<char> _M_f;
     };
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename _Traits>
     struct formatter<basic_string_view<wchar_t, _Traits>, wchar_t>
     {
@@ -1974,6 +1983,7 @@ namespace __format
     private:
       __format::__formatter_str<wchar_t> _M_f;
     };
+#endif // USE_WCHAR_T
   /// @}
 
   /// Format an integer.
@@ -2144,10 +2154,8 @@ namespace __format
 	    __str = string_view(__buf, __n);
 	  else
 	    {
-	      const std::locale& __loc = __fc.locale();
-	      auto& __ct = use_facet<ctype<_CharT>>(__loc);
 	      auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
-	      __ct.widen(__buf, __buf + __n, __p);
+	      __to_wstring_numeric(__buf, __n, __p);
 	      __str = wstring_view(__p, __n);
 	    }
 
@@ -3698,25 +3706,33 @@ namespace __format
     vformat_to(_Out __out, string_view __fmt, format_args __args)
     { return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename _Out> requires output_iterator<_Out, const wchar_t&>
     [[__gnu__::__always_inline__]]
     inline _Out
     vformat_to(_Out __out, wstring_view __fmt, wformat_args __args)
     { return __format::__do_vformat_to(std::move(__out), __fmt, __args); }
+#endif
 
   template<typename _Out> requires output_iterator<_Out, const char&>
     [[__gnu__::__always_inline__]]
     inline _Out
     vformat_to(_Out __out, const locale& __loc, string_view __fmt,
 	       format_args __args)
-    { return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc); }
+    {
+      return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc);
+    }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename _Out> requires output_iterator<_Out, const wchar_t&>
     [[__gnu__::__always_inline__]]
     inline _Out
     vformat_to(_Out __out, const locale& __loc, wstring_view __fmt,
 	       wformat_args __args)
-    { return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc); }
+    {
+      return __format::__do_vformat_to(std::move(__out), __fmt, __args, &__loc);
+    }
+#endif
 
   [[nodiscard]]
   inline string
@@ -3727,6 +3743,7 @@ namespace __format
     return std::move(__buf).get();
   }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   [[nodiscard]]
   inline wstring
   vformat(wstring_view __fmt, wformat_args __args)
@@ -3735,6 +3752,7 @@ namespace __format
     std::vformat_to(__buf.out(), __fmt, __args);
     return std::move(__buf).get();
   }
+#endif
 
   [[nodiscard]]
   inline string
@@ -3745,6 +3763,7 @@ namespace __format
     return std::move(__buf).get();
   }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   [[nodiscard]]
   inline wstring
   vformat(const locale& __loc, wstring_view __fmt, wformat_args __args)
@@ -3753,6 +3772,7 @@ namespace __format
     std::vformat_to(__buf.out(), __loc, __fmt, __args);
     return std::move(__buf).get();
   }
+#endif
 
   template<typename... _Args>
     [[nodiscard]]
@@ -3760,11 +3780,13 @@ namespace __format
     format(format_string<_Args...> __fmt, _Args&&... __args)
     { return std::vformat(__fmt.get(), std::make_format_args(__args...)); }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename... _Args>
     [[nodiscard]]
     inline wstring
     format(wformat_string<_Args...> __fmt, _Args&&... __args)
     { return std::vformat(__fmt.get(), std::make_wformat_args(__args...)); }
+#endif
 
   template<typename... _Args>
     [[nodiscard]]
@@ -3776,6 +3798,7 @@ namespace __format
 			  std::make_format_args(__args...));
     }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename... _Args>
     [[nodiscard]]
     inline wstring
@@ -3785,6 +3808,7 @@ namespace __format
       return std::vformat(__loc, __fmt.get(),
 			  std::make_wformat_args(__args...));
     }
+#endif
 
   template<typename _Out, typename... _Args>
     requires output_iterator<_Out, const char&>
@@ -3795,6 +3819,7 @@ namespace __format
 			     std::make_format_args(std::forward<_Args>(__args)...));
     }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename _Out, typename... _Args>
     requires output_iterator<_Out, const wchar_t&>
     inline _Out
@@ -3803,6 +3828,7 @@ namespace __format
       return std::vformat_to(std::move(__out), __fmt.get(),
 			     std::make_wformat_args(std::forward<_Args>(__args)...));
     }
+#endif
 
   template<typename _Out, typename... _Args>
     requires output_iterator<_Out, const char&>
@@ -3814,6 +3840,7 @@ namespace __format
 			     std::make_format_args(std::forward<_Args>(__args)...));
     }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename _Out, typename... _Args>
     requires output_iterator<_Out, const wchar_t&>
     inline _Out
@@ -3823,6 +3850,7 @@ namespace __format
       return std::vformat_to(std::move(__out), __loc, __fmt.get(),
 			     std::make_wformat_args(std::forward<_Args>(__args)...));
     }
+#endif
 
   template<typename _Out, typename... _Args>
     requires output_iterator<_Out, const char&>
@@ -3836,6 +3864,7 @@ namespace __format
       return std::move(__sink)._M_finish();
     }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename _Out, typename... _Args>
     requires output_iterator<_Out, const wchar_t&>
     inline format_to_n_result<_Out>
@@ -3847,6 +3876,7 @@ namespace __format
 		      std::make_wformat_args(__args...));
       return std::move(__sink)._M_finish();
     }
+#endif
 
   template<typename _Out, typename... _Args>
     requires output_iterator<_Out, const char&>
@@ -3860,6 +3890,7 @@ namespace __format
       return std::move(__sink)._M_finish();
     }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename _Out, typename... _Args>
     requires output_iterator<_Out, const wchar_t&>
     inline format_to_n_result<_Out>
@@ -3871,6 +3902,7 @@ namespace __format
 		      std::make_wformat_args(__args...));
       return std::move(__sink)._M_finish();
     }
+#endif
 
 /// @cond undocumented
 namespace __format
@@ -3927,6 +3959,7 @@ namespace __format
       return __buf.count();
     }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename... _Args>
     [[nodiscard]]
     inline size_t
@@ -3937,6 +3970,7 @@ namespace __format
 		      std::make_wformat_args(std::forward<_Args>(__args)...));
       return __buf.count();
     }
+#endif
 
   template<typename... _Args>
     [[nodiscard]]
@@ -3950,6 +3984,7 @@ namespace __format
       return __buf.count();
     }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   template<typename... _Args>
     [[nodiscard]]
     inline size_t
@@ -3961,6 +3996,7 @@ namespace __format
 		      std::make_wformat_args(std::forward<_Args>(__args)...));
       return __buf.count();
     }
+#endif
 
 #if __cpp_lib_format_ranges
   // [format.range], formatting of ranges
diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc b/libstdc++-v3/testsuite/std/format/functions/format.cc
index 59ed3be8baa..59d327fccee 100644
--- a/libstdc++-v3/testsuite/std/format/functions/format.cc
+++ b/libstdc++-v3/testsuite/std/format/functions/format.cc
@@ -274,6 +274,16 @@ test_wchar()
   VERIFY( s == L"0.0625" );
   s = std::format(L"{}", 0.25);
   VERIFY( s == L"0.25" );
+  s = std::format(L"{:+a} {:A}", 0x1.23p45, -0x1.abcdefp-15);
+  VERIFY( s == L"+1.23p+45 -1.ABCDEFP-15" );
+
+  double inf = std::numeric_limits<double>::infinity();
+  double nan = std::numeric_limits<double>::quiet_NaN();
+  s = std::format(L"{0} {0:F} {1} {1:E}", -inf, -nan);
+  VERIFY( s == L"-inf -INF -nan -NAN" );
+
+  s = std::format(L"{0:#b} {0:#B} {0:#x} {0:#X}", 99);
+  VERIFY( s == L"0b1100011 0B1100011 0x63 0X63" );
 }
 
 void
-- 
2.41.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [committed] libstdc++: Fix incomplete rework of wchar_t support in std::format
  2023-08-17 20:31 [committed] libstdc++: Rework std::format support for wchar_t Jonathan Wakely
@ 2023-08-18  8:44 ` Jonathan Wakely
  2023-08-18 11:31   ` [committed] libstdc++: Replace non-type-dependent uses of wchar_t in <format> and <chrono> Jonathan Wakely
  0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Wakely @ 2023-08-18  8:44 UTC (permalink / raw)
  To: libstdc++, gcc-patches

Tested x86_64-linux. Pushed to trunk.

-- >8 --

r14-3300-g023a62b77f999b left make_wformat_args and some uses of
std::wformat_context unguarded by _GLIBCXX_USE_WCHAR_T.

libstdc++-v3/ChangeLog:

	* include/bits/chrono_io.h (operator<<): Use __format_context.
	* include/std/format (__format::__format_context): New alias
	template.
	[!_GLIBCXX_USE_WCHAR_T] (wformat_args, make_wformat_arg):
	Disable.
---
 libstdc++-v3/include/bits/chrono_io.h | 15 +++++----------
 libstdc++-v3/include/std/format       | 13 +++++++++----
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index 05caa64fb7c..e16302baf84 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -2263,8 +2263,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d)
     {
-      using _Ctx = __conditional_t<is_same_v<_CharT, char>,
-				   format_context, wformat_context>;
+      using _Ctx = __format::__format_context<_CharT>;
       using _Str = basic_string_view<_CharT>;
       _Str __s = _GLIBCXX_WIDEN("{:02d} is not a valid day");
       if (__d.ok())
@@ -2291,8 +2290,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os, const month& __m)
     {
-      using _Ctx = __conditional_t<is_same_v<_CharT, char>,
-				   format_context, wformat_context>;
+      using _Ctx = __format::__format_context<_CharT>;
       using _Str = basic_string_view<_CharT>;
       _Str __s = _GLIBCXX_WIDEN("{:L%b}{} is not a valid month");
       if (__m.ok())
@@ -2322,8 +2320,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os, const year& __y)
     {
-      using _Ctx = __conditional_t<is_same_v<_CharT, char>,
-				   format_context, wformat_context>;
+      using _Ctx = __format::__format_context<_CharT>;
       using _Str = basic_string_view<_CharT>;
       _Str __s = _GLIBCXX_WIDEN("-{:04d} is not a valid year");
       if (__y.ok())
@@ -2355,8 +2352,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd)
     {
-      using _Ctx = __conditional_t<is_same_v<_CharT, char>,
-				   format_context, wformat_context>;
+      using _Ctx = __format::__format_context<_CharT>;
       using _Str = basic_string_view<_CharT>;
       _Str __s = _GLIBCXX_WIDEN("{:L%a}{} is not a valid weekday");
       if (__wd.ok())
@@ -2544,8 +2540,7 @@ namespace __detail
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const year_month_day& __ymd)
     {
-      using _Ctx = __conditional_t<is_same_v<_CharT, char>,
-				   format_context, wformat_context>;
+      using _Ctx = __format::__format_context<_CharT>;
       using _Str = basic_string_view<_CharT>;
       _Str __s = _GLIBCXX_WIDEN("{:%F} is not a valid date");
       __os << std::vformat(__ymd.ok() ? __s.substr(0, 5) : __s,
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 13f700a10bf..0b1ae8201af 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -74,20 +74,23 @@ namespace __format
   // Output iterator that writes to a type-erase character sink.
   template<typename _CharT>
     class _Sink_iter;
+
+  template<typename _CharT>
+    using __format_context = basic_format_context<_Sink_iter<_CharT>, _CharT>;
 } // namespace __format
 /// @endcond
 
-  using format_context
-    = basic_format_context<__format::_Sink_iter<char>, char>;
+  using format_context  = __format::__format_context<char>;
 #ifdef _GLIBCXX_USE_WCHAR_T
-  using wformat_context
-    = basic_format_context<__format::_Sink_iter<wchar_t>, wchar_t>;
+  using wformat_context = __format::__format_context<wchar_t>;
 #endif
 
   // [format.args], class template basic_format_args
   template<typename _Context> class basic_format_args;
   using format_args = basic_format_args<format_context>;
+#ifdef _GLIBCXX_USE_WCHAR_T
   using wformat_args = basic_format_args<wformat_context>;
+#endif
 
   // [format.arguments], arguments
   // [format.arg], class template basic_format_arg
@@ -3505,12 +3508,14 @@ namespace __format
       return _Store(__fmt_args...);
     }
 
+#ifdef _GLIBCXX_USE_WCHAR_T
   /// Capture formatting arguments for use by `std::vformat` (for wide output).
   template<typename... _Args>
     [[nodiscard,__gnu__::__always_inline__]]
     inline auto
     make_wformat_args(_Args&&... __args) noexcept
     { return std::make_format_args<wformat_context>(__args...); }
+#endif
 
 /// @cond undocumented
 namespace __format
-- 
2.41.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [committed] libstdc++: Replace non-type-dependent uses of wchar_t in <format> and <chrono>
  2023-08-18  8:44 ` [committed] libstdc++: Fix incomplete rework of wchar_t support in std::format Jonathan Wakely
@ 2023-08-18 11:31   ` Jonathan Wakely
  0 siblings, 0 replies; 3+ messages in thread
From: Jonathan Wakely @ 2023-08-18 11:31 UTC (permalink / raw)
  To: libstdc++, gcc-patches

This should be really fixed now!

Tested x86_64-linux. Pushed to trunk.

-- >8 --

This is one more piece of the rework to make wchar_t support in
std::format depend on _GLIBCXX_USE_WCHAR_T.

In <format> the __to_wstring_numeric function is called with arguments
that aren't type-dependent, so a declaration needs to be available, or
the calls need to be guarded by _GLIBCXX_USE_WCHAR_T.

In <chrono> there is a similarly non-type-dependent call to std::format
with a wchar_t format string, which is ill-formed when the wchar_t
overloads of std::format are not declared. Use _GLIBCXX_WIDEN to make it
type-dependent.

libstdc++-v3/ChangeLog:

	* include/bits/chrono_io.h (operator<<): Make uses of wide
	strings with streams and std::format type-dependent on _CharT.
	* include/std/format [!_GLIBCXX_USE_WCHAR_T] Do not use
	__to_wstring_numeric.
---
 libstdc++-v3/include/bits/chrono_io.h | 17 ++++++-----------
 libstdc++-v3/include/std/format       | 10 ++++++++--
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index e16302baf84..d558802e7d8 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -2390,15 +2390,14 @@ namespace __detail
       __os2.imbue(__os.getloc());
       __os2 << __wdi.weekday();
       const auto __i = __wdi.index();
-      if constexpr (is_same_v<_CharT, char>)
-	__os2 << std::format("[{}", __i);
-      else
-	__os2 << std::format(L"[{}", __i);
-      basic_string_view<_CharT> __s = _GLIBCXX_WIDEN(" is not a valid index]");
+      basic_string_view<_CharT> __s
+	= _GLIBCXX_WIDEN("[ is not a valid index]");
+      __os2 << __s[0];
+      __os2 << std::format(_GLIBCXX_WIDEN("{}"), __i);
       if (__i >= 1 && __i <= 5)
 	__os2 << __s.back();
       else
-	__os2 << __s;
+	__os2 << __s.substr(1);
       __os << __os2.view();
       return __os;
     }
@@ -2457,11 +2456,7 @@ namespace __detail
       // As above, just write straight to a stringstream, as if by "{:L}/last"
       basic_stringstream<_CharT> __os2;
       __os2.imbue(__os.getloc());
-      __os2 << __mdl.month();
-      if constexpr (is_same_v<_CharT, char>)
-	__os2 << "/last";
-      else
-	__os2 << L"/last";
+      __os2 << __mdl.month() << _GLIBCXX_WIDEN("/last");
       __os << __os2.view();
       return __os;
     }
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 0b1ae8201af..648f847ad96 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -1142,13 +1142,15 @@ namespace __format
 	  basic_string_view<_CharT> __str;
 	  if constexpr (is_same_v<char, _CharT>)
 	    __str = __narrow_str;
+#ifdef _GLIBCXX_USE_WCHAR_T
 	  else
 	    {
 	      size_t __n = __narrow_str.size();
 	      auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
-	      __to_wstring_numeric(__narrow_str.data(), __n, __p);
+	      std::__to_wstring_numeric(__narrow_str.data(), __n, __p);
 	      __str = {__p, __n};
 	    }
+#endif
 
 	  if (_M_spec._M_localized)
 	    {
@@ -1624,11 +1626,13 @@ namespace __format
 	  basic_string_view<_CharT> __str;
 	  if constexpr (is_same_v<_CharT, char>)
 	    __str = __narrow_str;
+#ifdef _GLIBCXX_USE_WCHAR_T
 	  else
 	    {
 	      __wstr = std::__to_wstring_numeric(__narrow_str);
 	      __str = __wstr;
 	    }
+#endif
 
 	  if (_M_spec._M_localized)
 	    {
@@ -2290,12 +2294,14 @@ namespace __format
 	  basic_string_view<_CharT> __str;
 	  if constexpr (is_same_v<_CharT, char>)
 	    __str = string_view(__buf, __n);
+#ifdef _GLIBCXX_USE_WCHAR_T
 	  else
 	    {
 	      auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT));
-	      __to_wstring_numeric(__buf, __n, __p);
+	      std::__to_wstring_numeric(__buf, __n, __p);
 	      __str = wstring_view(__p, __n);
 	    }
+#endif
 
 #if _GLIBCXX_P2518R3
 	  if (_M_spec._M_zero_fill)
-- 
2.41.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-08-18 11:31 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-17 20:31 [committed] libstdc++: Rework std::format support for wchar_t Jonathan Wakely
2023-08-18  8:44 ` [committed] libstdc++: Fix incomplete rework of wchar_t support in std::format Jonathan Wakely
2023-08-18 11:31   ` [committed] libstdc++: Replace non-type-dependent uses of wchar_t in <format> and <chrono> Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).