aboutsummaryrefslogtreecommitdiff
path: root/gcc/dwarf2codeview.cc
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2024-07-31 16:32:44 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2024-08-23 13:39:35 +0100
commit43b8153c26655a7a00f1584fcb4f511dc5e45fab (patch)
tree1b9ab24e6abd63b4361e5d4d6a98b35dba61b5d3 /gcc/dwarf2codeview.cc
parent591b71993f15ed95eb38f3314f3d9ac159b9d051 (diff)
downloadgcc-43b8153c26655a7a00f1584fcb4f511dc5e45fab.zip
gcc-43b8153c26655a7a00f1584fcb4f511dc5e45fab.tar.gz
gcc-43b8153c26655a7a00f1584fcb4f511dc5e45fab.tar.bz2
libstdc++: Only use std::time_put in std::format for non-C locales
When testing on Solaris I noticed that std/time/year/io.cc was FAILing because the year 1642 was being formatted as "+(" by %Ey. This turns out to be because we defer to std::time_put for modified conversion specs, and std::time_put uses std::strftime, and that's undefined for years before 1970. In particular, years before 1900 mean that the tm_year field is negative, which then causes incorrect results from strftime on at least Solaris and AIX. I've raised the general problem with LWG, but we can fix the FAILing test case (and probably improve performance slightly) by ignoring the E and O modifiers when the formatting locale is the "C" locale. The modifiers have no effect for the C locale, so we can just treat %Ey as %y and format it directly. This doesn't fix anything when the formatting locale isn't the C locale, but that case is not adequately tested, so doesn't cause any FAIL right now! The naïve fix would be simply: if (__mod) if (auto __loc = _M_locale(__ctx); __loc != locale::classic()) // ... However when the format string doesn't use the 'L' option, _M_locale always returns locale::classic(). In that case, we make a copy of the classic locale (which calls the non-inline copy constructor in the library), then make another copy of the classic locale, then compare the two. We can avoid all that by checking for the 'L' option first, instead of letting _M_locale do that: if (__mod && _M_spec._M_localized) if (auto __loc = __ctx.locale(); __loc != locale::classic()) // ... We could optimize this further if we had a __is_classic(__loc) function that would do the __loc == locale::classic() check without making any copies or non-inline calls. That would require examining the locale's _M_impl member, and probably require checking its name, because the locale::_S_classic singleton is not exported from the library. For _M_S the change is slightly different from the other functions, because if we skip using std::time_put for %OS then we fall through to the code that potentially prints fractional seconds, but the %OS format only prints whole seconds. So we need to format whole seconds directly when not using std::time_put, instead of falling through to the code below. libstdc++-v3/ChangeLog: * include/bits/chrono_io.h (__formatter_chrono::_M_C_y_Y): Ignore modifiers unless the formatting locale is not the C locale. (__formatter_chrono::_M_d_e): Likewise. (__formatter_chrono::_M_H_I): Likewise. (__formatter_chrono::_M_m): Likewise. (__formatter_chrono::_M_M): Likewise. (__formatter_chrono::_M_S): Likewise. (__formatter_chrono::_M_u_w): Likewise. (__formatter_chrono::_M_U_V_W): Likewise.
Diffstat (limited to 'gcc/dwarf2codeview.cc')
0 files changed, 0 insertions, 0 deletions