[gcc r17-3771] libstdc++: Skip locale in chrono operator<< for integer seconds precision

Tomasz Kaminski tkaminsk@gcc.gnu.org
Sun Aug 30 13:41:36 GMT 2026


https://gcc.gnu.org/g:9c40d80365f334e01f6e864e62ca9965841774cb

commit r17-3771-g9c40d80365f334e01f6e864e62ca9965841774cb
Author: Anlai Lu <agicy@qq.com>
Date:   Sun Aug 30 14:35:54 2026 +0200

    libstdc++: Skip locale in chrono operator<< for integer seconds precision
    
    When _Duration uses integer seconds precision (period::den == 1, not
    floating-point), time_point formatting has no sub-second digits and
    therefore no locale-dependent components. Add __detail::__chrono_write_time
    that conditionally skips the locale argument for integer-second time_points,
    eliminating the format_to_n locale overload and the basic_format_context
    locale member initialization.
    
    Also add [[__gnu__::__always_inline__]] to __formatter_chrono::_M_subsecs
    to mitigate a small mixed-TU inlining regression.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/chrono_io.h (__detail::__chrono_write_time):
            New function that conditionally skips locale for integer-second
            time_points.
            (__formatter_chrono::_M_subsecs): Add __always_inline__.
            (operator<<(basic_ostream<...>, const hh_mm_ss<_Duration>&)):
            Use if constexpr to skip locale for integer-second durations.
            (operator<<(basic_ostream<...>, const zoned_time<_Duration>&))
            (operator<<(basic_ostream<...>, const sys_time<_Duration>&))
            (operator<<(basic_ostream<...>, const utc_time<_Duration>&))
            (operator<<(basic_ostream<...>, const tai_time<_Duration>&))
            (operator<<(basic_ostream<...>, const file_time<_Duration>&))
            (operator<<(basic_ostream<...>, const local_time<_Duration>&)):
            Use __chrono_write_time.
            (operator<<(basic_ostream<...>, const sys_days<_Duration>&)):
            Remove trailing semicolon.
    
    Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
    Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
    Signed-off-by: Anlai Lu <agicy@qq.com>

Diff:
---
 libstdc++-v3/include/bits/chrono_io.h | 44 +++++++++++++++++++++++++++--------
 1 file changed, 34 insertions(+), 10 deletions(-)

diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index 0044b5a2ecc8..eec12357fdf7 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -1656,6 +1656,7 @@ namespace __format
 	}
 
       template<typename _OutIter, typename _FormatContext>
+	[[__gnu__::__always_inline__]]
 	_OutIter
 	_M_subsecs(const _ChronoData<_CharT>& __t, _OutIter __out,
 		   _FormatContext& __ctx) const
@@ -3635,6 +3636,23 @@ namespace __detail
       return std::__ostream_insert(__os, __s.data(), __s.size());
     }
 
+  // Wrapper around __chrono_write that skips locale for
+  // integer-second time_points.
+  template<size_t _BufSize, typename _TimePoint, typename _CharT,
+	   typename _Traits>
+    [[__gnu__::__always_inline__]]
+    inline basic_ostream<_CharT, _Traits>&
+    __chrono_write_time(basic_ostream<_CharT, _Traits>& __os,
+			const _TimePoint& __tp)
+    {
+      using _Duration = typename _TimePoint::duration;
+      if constexpr (!treat_as_floating_point_v<typename _Duration::rep>
+		    && _Duration::period::den == 1)
+	return __chrono_write<_BufSize>(__os, __tp);
+      else
+	return __chrono_write<_BufSize>(__os, __tp, __os.getloc());
+    }
+
 } // namespace __detail
 /// @endcond
 
@@ -3740,7 +3758,7 @@ namespace __detail
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const weekday_last& __wdl)
     { return __detail::__chrono_write<128>(__os, __wdl, __os.getloc()); }
-    
+
   template<typename _CharT, typename _Traits>
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md)
@@ -3846,7 +3864,13 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const hh_mm_ss<_Duration>& __hms)
-    { return __detail::__chrono_write<64>(__os, __hms, __os.getloc()); }
+    {
+      if constexpr (!treat_as_floating_point_v<typename _Duration::rep>
+		    && _Duration::period::den == 1)
+	return __detail::__chrono_write<64>(__os, __hms);
+      else
+	return __detail::__chrono_write<64>(__os, __hms, __os.getloc());
+    }
 
 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
   /// Writes a sys_info object to an ostream in an unspecified format.
@@ -3866,7 +3890,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const zoned_time<_Duration, _TimeZonePtr>& __t)
-    { return __detail::__chrono_write<128>(__os, __t, __os.getloc()); }
+    { return __detail::__chrono_write_time<128>(__os, __t); }
 #endif
 
   template<typename _CharT, typename _Traits, typename _Duration>
@@ -3875,12 +3899,12 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const sys_time<_Duration>& __tp)
-    { return __detail::__chrono_write<64>(__os, __tp, __os.getloc()); }
+    { return __detail::__chrono_write_time<64>(__os, __tp); }
 
   template<typename _CharT, typename _Traits>
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_days& __dp)
-    { return __detail::__chrono_write<32>(__os, __dp); };
+    { return __detail::__chrono_write<32>(__os, __dp); }
 
   template<typename _CharT, typename _Traits, typename _Duration,
 	   typename _Alloc = allocator<_CharT>>
@@ -3914,7 +3938,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const utc_time<_Duration>& __t)
-    { return __detail::__chrono_write<64>(__os, __t, __os.getloc()); }
+    { return __detail::__chrono_write_time<64>(__os, __t); }
 
   template<typename _CharT, typename _Traits, typename _Duration,
 	   typename _Alloc = allocator<_CharT>>
@@ -3946,7 +3970,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const tai_time<_Duration>& __t)
-    { return __detail::__chrono_write<64>(__os, __t, __os.getloc()); }
+    { return __detail::__chrono_write_time<64>(__os, __t); }
 
   template<typename _CharT, typename _Traits, typename _Duration,
 	   typename _Alloc = allocator<_CharT>>
@@ -3982,7 +4006,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const gps_time<_Duration>& __t)
-    { return __detail::__chrono_write<64>(__os, __t, __os.getloc()); }
+    { return __detail::__chrono_write_time<64>(__os, __t); }
 
   template<typename _CharT, typename _Traits, typename _Duration,
 	   typename _Alloc = allocator<_CharT>>
@@ -4017,7 +4041,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
 	       const file_time<_Duration>& __t)
-    { return __detail::__chrono_write<64>(__os, __t, __os.getloc()); }
+    { return __detail::__chrono_write_time<64>(__os, __t); }
 
   template<typename _CharT, typename _Traits, typename _Duration,
 	   typename _Alloc = allocator<_CharT>>
@@ -4040,7 +4064,7 @@ namespace __detail
     // _GLIBCXX_RESOLVE_LIB_DEFECTS
     // 4257. Stream insertion for chrono::local_time should be constrained
     requires requires(const sys_time<_Duration>& __st) { __os << __st; }
-    { return __detail::__chrono_write<64>(__os, __lt, __os.getloc()); }
+    { return __detail::__chrono_write_time<64>(__os, __lt); }
 
   template<typename _CharT, typename _Traits, typename _Duration,
 	   typename _Alloc = allocator<_CharT>>


More information about the Libstdc++-cvs mailing list