On Fri, 10 Dec 2021 at 12:49, Jakub Jelinek via Libstdc++ <libstd...@gcc.gnu.org> wrote: > > Hi! > > This incremental patch adds std::time_get %r support (%p was added already > in the previous patch). The _M_am_fm_format method previously in the header > unfortunately had wrong arguments and so was useless, so the largest > complication in this patch is exporting a new symbol in the right symbol > version. > > Tested on x86_64-linux, ok for trunk?
Yes, this one is OK too, thanks! > > 2021-12-10 Jakub Jelinek <ja...@redhat.com> > > PR libstdc++/71367 > * config/locale/dragonfly/time_members.cc (_M_initialize_timepunct): > Initialize "C" _M_am_pm_format to %I:%M:%S %p rather than empty > string. > * config/locale/gnu/time_members.cc (_M_initialize_timepunct): > Likewise. > * config/locale/generic/time_members.cc (_M_initialize_timepunct): > Likewise. > * include/bits/locale_facets_nonio.h (_M_am_pm_format): New method. > * include/bits/locale_facets_nonio.tcc (_M_extract_via_format): Handle > %r. > * config/abi/pre/gnu.ver (GLIBCXX_3.4.30): Export _M_am_pm_format > with const _CharT** argument, ensure it isn't exported in GLIBCXX_3.4. > * testsuite/22_locale/time_get/get/char/71367.cc: New test. > * testsuite/22_locale/time_get/get/wchar_t/71367.cc: New test. > > --- libstdc++-v3/config/locale/dragonfly/time_members.cc.jj 2021-01-05 > 00:13:58.281297350 +0100 > +++ libstdc++-v3/config/locale/dragonfly/time_members.cc 2021-12-10 > 12:27:18.350425776 +0100 > @@ -74,7 +74,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > _M_data->_M_date_time_era_format = ""; > _M_data->_M_am = "AM"; > _M_data->_M_pm = "PM"; > - _M_data->_M_am_pm_format = ""; > + _M_data->_M_am_pm_format = "%I:%M:%S %p"; > > // Day names, starting with "C"'s Sunday. > _M_data->_M_day1 = "Sunday"; > @@ -231,7 +231,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > _M_data->_M_date_time_era_format = L""; > _M_data->_M_am = L"AM"; > _M_data->_M_pm = L"PM"; > - _M_data->_M_am_pm_format = L""; > + _M_data->_M_am_pm_format = L"%I:%M:%S %p"; > > // Day names, starting with "C"'s Sunday. > _M_data->_M_day1 = L"Sunday"; > --- libstdc++-v3/config/locale/gnu/time_members.cc.jj 2021-01-05 > 00:13:58.282297338 +0100 > +++ libstdc++-v3/config/locale/gnu/time_members.cc 2021-12-10 > 12:26:52.979787605 +0100 > @@ -80,7 +80,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > _M_data->_M_date_time_era_format = ""; > _M_data->_M_am = "AM"; > _M_data->_M_pm = "PM"; > - _M_data->_M_am_pm_format = ""; > + _M_data->_M_am_pm_format = "%I:%M:%S %p"; > > // Day names, starting with "C"'s Sunday. > _M_data->_M_day1 = "Sunday"; > @@ -236,7 +236,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > _M_data->_M_date_time_era_format = L""; > _M_data->_M_am = L"AM"; > _M_data->_M_pm = L"PM"; > - _M_data->_M_am_pm_format = L""; > + _M_data->_M_am_pm_format = L"%I:%M:%S %p"; > > // Day names, starting with "C"'s Sunday. > _M_data->_M_day1 = L"Sunday"; > --- libstdc++-v3/config/locale/generic/time_members.cc.jj 2021-01-05 > 00:13:58.282297338 +0100 > +++ libstdc++-v3/config/locale/generic/time_members.cc 2021-12-10 > 12:27:55.433896906 +0100 > @@ -72,7 +72,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > _M_data->_M_date_time_era_format = ""; > _M_data->_M_am = "AM"; > _M_data->_M_pm = "PM"; > - _M_data->_M_am_pm_format = ""; > + _M_data->_M_am_pm_format = "%I:%M:%S %p"; > > // Day names, starting with "C"'s Sunday. > _M_data->_M_day1 = "Sunday"; > @@ -157,7 +157,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > _M_data->_M_date_time_era_format = L""; > _M_data->_M_am = L"AM"; > _M_data->_M_pm = L"PM"; > - _M_data->_M_am_pm_format = L""; > + _M_data->_M_am_pm_format = L"%I:%M:%S %p"; > > // Day names, starting with "C"'s Sunday. > _M_data->_M_day1 = L"Sunday"; > --- libstdc++-v3/include/bits/locale_facets_nonio.h.jj 2021-04-06 > 23:49:08.318882385 +0200 > +++ libstdc++-v3/include/bits/locale_facets_nonio.h 2021-12-10 > 12:55:26.240337962 +0100 > @@ -243,6 +243,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > #endif > > void > + _M_am_pm_format(const _CharT** __ampm_format) const > + { > + __ampm_format[0] = _M_data->_M_am_pm_format; > + } > + > + void > _M_am_pm(const _CharT** __ampm) const > { > __ampm[0] = _M_data->_M_am; > --- libstdc++-v3/include/bits/locale_facets_nonio.tcc.jj 2021-12-09 > 22:52:34.892266539 +0100 > +++ libstdc++-v3/include/bits/locale_facets_nonio.tcc 2021-12-10 > 12:56:02.721816838 +0100 > @@ -806,6 +806,13 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 > if (!__tmperr && __mem) > __tm->tm_hour += 12; > break; > + case 'r': > + // Locale's 12-hour clock time format (in C %I:%M:%S %p). > + const char_type* __ampm_format; > + __tp._M_am_pm_format(&__ampm_format); > + __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, > + __tm, __ampm_format); > + break; > case 'R': > // Equivalent to (%H:%M). > __cs = "%H:%M"; > --- libstdc++-v3/config/abi/pre/gnu.ver.jj 2021-11-12 23:02:20.247930376 > +0100 > +++ libstdc++-v3/config/abi/pre/gnu.ver 2021-12-10 13:22:34.569067900 +0100 > @@ -185,7 +185,13 @@ GLIBCXX_3.4 { > std::_List_node_base::unhook*; > std::_List_node_base::reverse*; > std::_List_node_base::transfer*; > - std::__timepunct*; > +# std::__timepunct*; > + std::__timepunct?char?::[^_]*; > + std::__timepunct?char?::_[^M]*; > + std::__timepunct?char?::_M_[^a]*; > + std::__timepunct?wchar_t?::[^_]*; > + std::__timepunct?wchar_t?::_[^M]*; > + std::__timepunct?wchar_t?::_M_[^a]*; > # std::__numeric_limits_base*; > std::__num_base::_S_format_float*; > std::__num_base::_S_format_int*; > @@ -684,6 +690,10 @@ GLIBCXX_3.4 { > # std::__convert_to_v > _ZSt14__convert_to_vI[^gU]*; > > + # std::__timepunct > + _ZNKSt11__timepunctI[cw]E8_M_am_pmEPPK[cw]; > + _ZNKSt11__timepunctI[cw]E15_M_am_pm_formatEPK[cw]; > + > # __gnu_cxx::stdio_sync_filebuf > _ZTVN9__gnu_cxx18stdio_sync_filebufI[cw]St11char_traitsI[cw]EEE; > > @@ -2401,6 +2411,9 @@ GLIBCXX_3.4.30 { > > _ZSt21__glibcxx_assert_fail*; > > + # std::__timepunct<char>::_M_am_pm_format(const char**) > + _ZNKSt11__timepunctI[cw]E15_M_am_pm_formatEPPK[cw]; > + > } GLIBCXX_3.4.29; > > # Symbols in the support library (libsupc++) have their own tag. > --- libstdc++-v3/testsuite/22_locale/time_get/get/char/71367.cc.jj > 2021-12-10 12:38:54.910491672 +0100 > +++ libstdc++-v3/testsuite/22_locale/time_get/get/char/71367.cc 2021-12-10 > 12:41:36.540186566 +0100 > @@ -0,0 +1,67 @@ > +// { dg-do run { target c++11 } } > + > +// Copyright (C) 2021 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > + > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > + > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// <http://www.gnu.org/licenses/>. > + > +#include <locale> > +#include <sstream> > +#include <iterator> > +#include <testsuite_hooks.h> > + > +void > +test01() > +{ > + using namespace std; > + > + locale loc_c = locale::classic(); > + > + istringstream iss; > + iss.imbue(loc_c); > + const time_get<char>& tget = use_facet<time_get<char>>(iss.getloc()); > + typedef istreambuf_iterator<char> iter; > + const iter end; > + > + tm time; > + ios_base::iostate err = ios_base::badbit; > + > + iss.str("01:38:12 PM"); > + string format = "%I:%M:%S %p"; > + auto ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_hour == 13 ); > + VERIFY( time.tm_min == 38 ); > + VERIFY( time.tm_sec == 12 ); > + > + iss.str("11:17:42 PM"); > + format = "%r"; > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_hour == 23 ); > + VERIFY( time.tm_min == 17 ); > + VERIFY( time.tm_sec == 42 ); > +} > + > +int > +main() > +{ > + test01(); > + return 0; > +} > --- libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/71367.cc.jj > 2021-12-10 12:41:53.890939115 +0100 > +++ libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/71367.cc > 2021-12-10 12:42:59.996996334 +0100 > @@ -0,0 +1,67 @@ > +// { dg-do run { target c++11 } } > + > +// Copyright (C) 2021 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > + > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > + > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// <http://www.gnu.org/licenses/>. > + > +#include <locale> > +#include <sstream> > +#include <iterator> > +#include <testsuite_hooks.h> > + > +void > +test01() > +{ > + using namespace std; > + > + locale loc_c = locale::classic(); > + > + wistringstream iss; > + iss.imbue(loc_c); > + const time_get<wchar_t>& tget = use_facet<time_get<wchar_t>>(iss.getloc()); > + typedef istreambuf_iterator<wchar_t> iter; > + const iter end; > + > + tm time; > + ios_base::iostate err = ios_base::badbit; > + > + iss.str(L"01:38:12 PM"); > + wstring format = L"%I:%M:%S %p"; > + auto ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_hour == 13 ); > + VERIFY( time.tm_min == 38 ); > + VERIFY( time.tm_sec == 12 ); > + > + iss.str(L"11:17:42 PM"); > + format = L"%r"; > + ret = tget.get(iter(iss), end, iss, err, &time, > + format.data(), format.data()+format.size()); > + VERIFY( err == ios_base::eofbit ); > + VERIFY( ret == end ); > + VERIFY( time.tm_hour == 23 ); > + VERIFY( time.tm_min == 17 ); > + VERIFY( time.tm_sec == 42 ); > +} > + > +int > +main() > +{ > + test01(); > + return 0; > +} > > Jakub >