aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Carlini <paolo.carlini@oracle.com>2010-01-07 00:22:51 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2010-01-07 00:22:51 +0000
commit2e8e6a99ee156e8cd15b5e4b9a0eeaa49e2a970b (patch)
tree4c72dfc64a8a21dead648354eaf800ea69e50865
parent83c3322912062f7254f542cf9334569e270caace (diff)
downloadgcc-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/ChangeLog13
-rw-r--r--libstdc++-v3/doc/xml/manual/prerequisites.xml1
-rw-r--r--libstdc++-v3/include/bits/locale_facets_nonio.tcc33
-rw-r--r--libstdc++-v3/testsuite/22_locale/time_get/get_date/char/26701.cc64
-rw-r--r--libstdc++-v3/testsuite/22_locale/time_get/get_date/wchar_t/26701.cc64
-rw-r--r--libstdc++-v3/testsuite/lib/libstdc++.exp1
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\");"