diff options
author | Jakub Jelinek <jakub@redhat.com> | 2022-01-10 15:38:47 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2022-01-10 15:38:47 +0100 |
commit | a8d3c98746098e2784be7144c1ccc9fcc34a0888 (patch) | |
tree | aa4b7c7d9031a5d49656f13d42d122c0c9b5f941 /libstdc++-v3/config/abi/pre/gnu.ver | |
parent | 68c2e9e9234cb301e9e81792cad233a41e797792 (diff) | |
download | gcc-a8d3c98746098e2784be7144c1ccc9fcc34a0888.zip gcc-a8d3c98746098e2784be7144c1ccc9fcc34a0888.tar.gz gcc-a8d3c98746098e2784be7144c1ccc9fcc34a0888.tar.bz2 |
libstdc++: Add %j, %U, %w, %W time_get support, fix %y, %Y, %C, %p [PR77760]
glibc strptime passes around some state, what fields in struct tm have been
set and what needs to be finalized through possibly recursive calls, and
at the end performs various finalizations, like applying %p so that it
works for both %I %p and %p %I orders, or applying century so that both
%C %y and %y %C works, or computation of missing fields from others
(e.g. from %Y and %j one can compute tm_mon, tm_mday and tm_wday,
from %Y %U %w, %Y %W %w, %Y %U %a, or %Y %W %w one can compute
tm_mon, tm_mday, tm_yday or e.g. from %Y %m %d one can compute tm_wday
and tm_yday.
As the finalization is quite large and doesn't need to be a template
(doesn't depend on any iterators or char types), I've put it into libstdc++,
and left some padding in the state struct, so that perhaps in the future we
can track some more state without changing ABI.
Unfortunately, there is an ugly problem that the standard mandates that
get method calls the do_get virtual method and I don't see how we can
cary on any state in between those calls (even if we did an ABI change
for the facets, the methods are const, so that I think multiple threads
could use the same time_get objects and we couldn't store state in there).
There is a hack for that for GCC (seems to work with ICC too, doesn't work
with clang++) if the do_get method isn't overriden we can pass the state
around.
For both do_get_year and per IRC discussions also for %y, the behavior is
if 1-2 digits are parsed, the year is treated according to POSIX 2008 %y
rules (0-68 is 2000-2068, 69-99 is 1969-1999), if 3-4 digits are parsed,
it is treated as %Y.
2022-01-10 Jakub Jelinek <jakub@redhat.com>
PR libstdc++/77760
* include/bits/locale_facets_nonio.h (__time_get_state): New struct.
(time_get::_M_extract_via_format): Declare new method with
__time_get_state& as an extra argument.
* include/bits/locale_facets_nonio.tcc (_M_extract_via_format): Add
__state argument, set various fields in it while parsing. Handle %j,
%U, %w and %W, fix up handling of %y, %Y and %C, don't adjust tm_hour
for %p immediately. Add a wrapper around the method without the
__state argument for backwards compatibility.
(_M_extract_num): Remove all __len == 4 special cases.
(time_get::do_get_time, time_get::do_get_date, time_get::do_get): Zero
initialize __state, pass it to _M_extract_via_format and finalize it
at the end.
(do_get_year): For 1-2 digit parsed years, map 0-68 to 2000-2068,
69-99 to 1969-1999. For 3-4 digit parsed years use that as year.
(get): If do_get isn't overloaded from the locale_facets_nonio.tcc
version, don't call do_get but call _M_extract_via_format instead to
pass around state.
* config/abi/pre/gnu.ver (GLIBCXX_3.4.30): Export _M_extract_via_format
with extra __time_get_state and __time_get_state::_M_finalize_state.
* src/c++98/locale_facets.cc (is_leap, day_of_the_week,
day_of_the_year): New functions in anon namespace.
(mon_yday): New var in anon namespace.
(__time_get_state::_M_finalize_state): Define.
* testsuite/22_locale/time_get/get/char/4.cc: New test.
* testsuite/22_locale/time_get/get/wchar_t/4.cc: New test.
* testsuite/22_locale/time_get/get_year/char/1.cc (test01): Parse 197
as year 197AD instead of error.
* testsuite/22_locale/time_get/get_year/char/5.cc (test01): Parse 1 as
year 2001 instead of error.
* testsuite/22_locale/time_get/get_year/char/6.cc: New test.
* testsuite/22_locale/time_get/get_year/wchar_t/1.cc (test01): Parse
197 as year 197AD instead of error.
* testsuite/22_locale/time_get/get_year/wchar_t/5.cc (test01): Parse
1 as year 2001 instead of error.
* testsuite/22_locale/time_get/get_year/wchar_t/6.cc: New test.
Diffstat (limited to 'libstdc++-v3/config/abi/pre/gnu.ver')
-rw-r--r-- | libstdc++-v3/config/abi/pre/gnu.ver | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index afd242b..dedee8c 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -628,7 +628,7 @@ GLIBCXX_3.4 { _ZNSt8time_get*; _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE1*; _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE8*; - _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE21*; + _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE21*PK[cw]; # std::time_get_byname _ZNSt15time_get_bynameI[cw]*EEEC[12]EPKc[jmy]; @@ -1887,7 +1887,9 @@ GLIBCXX_3.4.21 { _ZNKSt7__cxx119money_putI*; _ZNKSt7__cxx1110moneypunctI*; _ZNKSt7__cxx118numpunctI*; - _ZNKSt7__cxx118time_getI*; + _ZNKSt7__cxx118time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE[13-9]*; + _ZNKSt7__cxx118time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE21*PK[cw]; + _ZNKSt7__cxx118time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE24*; _ZSt9has_facetINSt7__cxx117collate*; _ZSt9has_facetINSt7__cxx118messages*; @@ -2427,6 +2429,12 @@ GLIBCXX_3.4.30 { # Only defined #if ! __GXX_TYPEINFO_EQUALITY_INLINE _ZNKSt9type_info7__equalERKS_; + # std::time_get + _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE21*__time_get_state; + _ZNKSt7__cxx118time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE21*__time_get_state; + + _ZNSt16__time_get_state17_M_finalize_stateEP2tm; + } GLIBCXX_3.4.29; # Symbols in the support library (libsupc++) have their own tag. |