diff options
author | Paolo Carlini <paolo.carlini@oracle.com> | 2010-01-07 00:22:51 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2010-01-07 00:22:51 +0000 |
commit | 2e8e6a99ee156e8cd15b5e4b9a0eeaa49e2a970b (patch) | |
tree | 4c72dfc64a8a21dead648354eaf800ea69e50865 | |
parent | 83c3322912062f7254f542cf9334569e270caace (diff) | |
download | gcc-2e8e6a99ee156e8cd15b5e4b9a0eeaa49e2a970b.zip gcc-2e8e6a99ee156e8cd15b5e4b9a0eeaa49e2a970b.tar.gz gcc-2e8e6a99ee156e8cd15b5e4b9a0eeaa49e2a970b.tar.bz2 |
re PR libstdc++/26701 (std::time_get parses only 2 digits of year, in en_GB locale.)
2010-01-06 Paolo Carlini <paolo.carlini@oracle.com>
PR libstdc++/26701
* include/bits/locale_facets_nonio.tcc (time_get<>::_M_extract_num):
Encode short two digits over four parsings to negative numbers.
(time_get<>::_M_extract_via_format): Adjust, accept both two digits
and four digits for both 'y' and 'Y'.
(time_get<>::do_get_year): Call time_get<>::_M_extract_num.
* doc/xml/manual/prerequisites.xml: Add en_GB.
* testsuite/lib/libstdc++.exp: Adjust
* testsuite/22_locale/time_get/get_date/char/26701.cc: New.
* testsuite/22_locale/time_get/get_date/wchar_t/26701.cc: Likewise.
From-SVN: r155685
-rw-r--r-- | libstdc++-v3/ChangeLog | 13 | ||||
-rw-r--r-- | libstdc++-v3/doc/xml/manual/prerequisites.xml | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/locale_facets_nonio.tcc | 33 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/22_locale/time_get/get_date/char/26701.cc | 64 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/22_locale/time_get/get_date/wchar_t/26701.cc | 64 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/lib/libstdc++.exp | 1 |
6 files changed, 158 insertions, 18 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 02c19c1..cb10263 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2010-01-06 Paolo Carlini <paolo.carlini@oracle.com> + + PR libstdc++/26701 + * include/bits/locale_facets_nonio.tcc (time_get<>::_M_extract_num): + Encode short two digits over four parsings to negative numbers. + (time_get<>::_M_extract_via_format): Adjust, accept both two digits + and four digits for both 'y' and 'Y'. + (time_get<>::do_get_year): Call time_get<>::_M_extract_num. + * doc/xml/manual/prerequisites.xml: Add en_GB. + * testsuite/lib/libstdc++.exp: Adjust + * testsuite/22_locale/time_get/get_date/char/26701.cc: New. + * testsuite/22_locale/time_get/get_date/wchar_t/26701.cc: Likewise. + 2010-01-06 Benjamin Kosnik <bkoz@redhat.com> PR libstdc++/42491 diff --git a/libstdc++-v3/doc/xml/manual/prerequisites.xml b/libstdc++-v3/doc/xml/manual/prerequisites.xml index 6a55e0c..8391fe4 100644 --- a/libstdc++-v3/doc/xml/manual/prerequisites.xml +++ b/libstdc++-v3/doc/xml/manual/prerequisites.xml @@ -73,6 +73,7 @@ <programlisting> de_DE ISO-8859-1 de_DE@euro ISO-8859-15 +en_GB ISO-8859-1 en_HK ISO-8859-1 en_PH ISO-8859-1 en_US ISO-8859-1 diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc index 73cd747..e788457 100644 --- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc +++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc @@ -778,16 +778,16 @@ _GLIBCXX_END_LDBL_NAMESPACE break; case 'y': case 'C': // C99 - // Two digit year. [tm_year] - __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, - __io, __tmperr); - break; + // Two digit year. case 'Y': - // Year [1900). [tm_year] + // Year [1900). + // NB: We parse either two digits, implicitly years since + // 1900, or 4 digits, full year. In both cases we can + // reconstruct [tm_year]. See also libstdc++/26701. __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4, __io, __tmperr); if (!__tmperr) - __tm->tm_year = __mem - 1900; + __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900; break; case 'Z': // Timezone info. @@ -865,6 +865,9 @@ _GLIBCXX_END_LDBL_NAMESPACE } if (__i == __len) __member = __value; + // Special encoding for do_get_year, 'y', and 'Y' above. + else if (__len == 4 && __i == 2) + __member = __value - 100; else __err |= ios_base::failbit; @@ -1116,19 +1119,13 @@ _GLIBCXX_END_LDBL_NAMESPACE { const locale& __loc = __io._M_getloc(); const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); + int __tmpyear; + ios_base::iostate __tmperr = ios_base::goodbit; - size_t __i = 0; - int __value = 0; - for (; __beg != __end && __i < 4; ++__beg, ++__i) - { - const char __c = __ctype.narrow(*__beg, '*'); - if (__c >= '0' && __c <= '9') - __value = __value * 10 + (__c - '0'); - else - break; - } - if (__i == 2 || __i == 4) - __tm->tm_year = __i == 2 ? __value : __value - 1900; + __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4, + __io, __tmperr); + if (!__tmperr) + __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900; else __err |= ios_base::failbit; diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get_date/char/26701.cc b/libstdc++-v3/testsuite/22_locale/time_get/get_date/char/26701.cc new file mode 100644 index 0000000..b02fefe --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/time_get/get_date/char/26701.cc @@ -0,0 +1,64 @@ +// { dg-require-namedlocale "" } + +// 2010-01-06 Paolo Carlini <paolo.carlini@oracle.com> + +// Copyright (C) 2010 Free Software Foundation +// +// 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/>. + +// 22.2.5.1.1 time_get members + +#include <locale> +#include <sstream> +#include <testsuite_hooks.h> + +// libstdc++/26701 +void test01() +{ + using namespace std; + bool test __attribute__((unused)) = true; + + typedef istreambuf_iterator<char> iterator_type; + + locale loc_en = locale("en_GB"); + + tm tm0 = __gnu_test::test_tm(0, 0, 0, 0, 0, 0, 0, 0, 0); + + iterator_type end; + + istringstream iss; + iss.imbue(loc_en); + const time_get<char>& tg = use_facet<time_get<char> >(iss.getloc()); + + const ios_base::iostate good = ios_base::goodbit; + ios_base::iostate errorstate = good; + + iss.str("01/02/2003"); + iterator_type is_it0(iss); + + errorstate = good; + tg.get_date(is_it0, end, iss, errorstate, &tm0); + VERIFY( errorstate == ios_base::eofbit ); + VERIFY( tm0.tm_year + 1900 == 2003 ); + VERIFY( tm0.tm_mon + 1 == 2 ); + VERIFY( tm0.tm_mday == 1 ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get_date/wchar_t/26701.cc b/libstdc++-v3/testsuite/22_locale/time_get/get_date/wchar_t/26701.cc new file mode 100644 index 0000000..2f4980a --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/time_get/get_date/wchar_t/26701.cc @@ -0,0 +1,64 @@ +// { dg-require-namedlocale "" } + +// 2010-01-06 Paolo Carlini <paolo.carlini@oracle.com> + +// Copyright (C) 2010 Free Software Foundation +// +// 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/>. + +// 22.2.5.1.1 time_get members + +#include <locale> +#include <sstream> +#include <testsuite_hooks.h> + +// libstdc++/26701 +void test01() +{ + using namespace std; + bool test __attribute__((unused)) = true; + + typedef istreambuf_iterator<wchar_t> iterator_type; + + locale loc_en = locale("en_GB"); + + tm tm0 = __gnu_test::test_tm(0, 0, 0, 0, 0, 0, 0, 0, 0); + + iterator_type end; + + wistringstream iss; + iss.imbue(loc_en); + const time_get<wchar_t>& tg = use_facet<time_get<wchar_t> >(iss.getloc()); + + const ios_base::iostate good = ios_base::goodbit; + ios_base::iostate errorstate = good; + + iss.str(L"01/02/2003"); + iterator_type is_it0(iss); + + errorstate = good; + tg.get_date(is_it0, end, iss, errorstate, &tm0); + VERIFY( errorstate == ios_base::eofbit ); + VERIFY( tm0.tm_year + 1900 == 2003 ); + VERIFY( tm0.tm_mon + 1 == 2 ); + VERIFY( tm0.tm_mday == 1 ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp index 09cae6d..45a43de 100644 --- a/libstdc++-v3/testsuite/lib/libstdc++.exp +++ b/libstdc++-v3/testsuite/lib/libstdc++.exp @@ -869,6 +869,7 @@ proc check_v3_target_namedlocale { } { puts $f " locale(\"de_DE\");" puts $f " locale(\"de_DE.ISO-8859-15@euro\");" puts $f " locale(\"de_DE@euro\");" + puts $f " locale(\"en_GB\");" puts $f " locale(\"en_HK\");" puts $f " locale(\"en_PH\");" puts $f " locale(\"en_US\");" |