This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch] Fix libstdc++/9548 on the 3_3 branch


Hi,

the below is the version for the branch, regtested and
abi checked on x86-linux.

Ok?

Paolo.

//////////
2003-02-07  Paolo Carlini  <pcarlini@unitus.it>

	PR libstdc++/9548
	Implement resolution of DR 231 (Ready)
	* include/bits/locale_facets.h (__num_base::_S_format_float):
	Return void.
	* src/locale.cc (__num_base::_S_format_float): Implement
	resolution of DR 231.
	* include/bits/locale_facets.tcc (num_put::_M_convert_float):
	Tweak uses. Check for negative precision.
	* testsuite/22_locale/num_put_members_char.cc (test06): Add
	* testsuite/22_locale/num_put_members_wchar_t.cc (test06): Ditto.
diff -urN libstdc++-v3-orig/include/bits/locale_facets.h libstdc++-v3/include/bits/locale_facets.h
--- libstdc++-v3-orig/include/bits/locale_facets.h	2003-02-06 09:33:03.000000000 +0100
+++ libstdc++-v3/include/bits/locale_facets.h	2003-02-07 13:25:58.000000000 +0100
@@ -546,8 +546,8 @@
 
     // num_put
     // Construct and return valid scanf format for floating point types.
-    static bool
-    _S_format_float(const ios_base& __io, char* __fptr, char __mod, 
+    static void
+    _S_format_float(const ios_base& __io, char* __fptr, char __mod,
 		    streamsize __prec);
     
     // Construct and return valid scanf format for integer types.
diff -urN libstdc++-v3-orig/include/bits/locale_facets.tcc libstdc++-v3/include/bits/locale_facets.tcc
--- libstdc++-v3-orig/include/bits/locale_facets.tcc	2003-02-06 09:33:03.000000000 +0100
+++ libstdc++-v3/include/bits/locale_facets.tcc	2003-02-07 13:27:01.000000000 +0100
@@ -634,6 +634,9 @@
 
 	if (__prec > static_cast<streamsize>(__max_digits))
 	  __prec = static_cast<streamsize>(__max_digits);
+	else if (__prec < static_cast<streamsize>(0))
+	  // Default precision.
+	  __prec = static_cast<streamsize>(6);
 
 	// Long enough for the max format spec.
 	char __fbuf[16];
@@ -646,24 +649,17 @@
 	int __cs_size = __max_digits * 3;
 	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
 
-	const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec);
-	if (__fp)
-	  __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
-				   _S_c_locale, __prec);
-	else
-	  __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
+	_S_format_float(__io, __fbuf, __mod, __prec);
+	__len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
+				 _S_c_locale, __prec);
 
 	// If the buffer was not large enough, try again with the correct size.
 	if (__len >= __cs_size)
 	  {
 	    __cs_size = __len + 1; 
 	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-	    if (__fp)
-	      __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
-				       _S_c_locale, __prec);
-	    else
-	      __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
-				       _S_c_locale);
+	    __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
+				     _S_c_locale, __prec);
 	  }
 #else
 	// Consider the possibility of long ios_base::fixed outputs
@@ -678,10 +674,8 @@
 	                              : __max_digits * 3;
 	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
 
-	if (_S_format_float(__io, __fbuf, __mod, __prec))
-	  __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
-	else
-	  __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
+	_S_format_float(__io, __fbuf, __mod, __prec);
+	__len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
 #endif
 	return _M_widen_float(__s, __io, __fill, __cs, __len);
       }
diff -urN libstdc++-v3-orig/src/locale.cc libstdc++-v3/src/locale.cc
--- libstdc++-v3-orig/src/locale.cc	2003-01-06 23:20:07.000000000 +0100
+++ libstdc++-v3/src/locale.cc	2003-02-07 13:25:08.000000000 +0100
@@ -504,11 +504,13 @@
 
   const char __num_base::_S_atoms[] = "0123456789eEabcdfABCDF";
 
-  bool
-  __num_base::_S_format_float(const ios_base& __io, char* __fptr, char __mod,
-			      streamsize __prec)
+  // _GLIBCPP_RESOLVE_LIB_DEFECTS
+  // According to the resolution of DR 231, about 22.2.2.2.2, p11,
+  // "str.precision() is specified in the conversion specification".
+  void
+  __num_base::_S_format_float(const ios_base& __io, char* __fptr,
+			      char __mod, streamsize /* unused post DR 231 */)
   {
-    bool __incl_prec = false;
     ios_base::fmtflags __flags = __io.flags();
     *__fptr++ = '%';
     // [22.2.2.2.2] Table 60
@@ -516,13 +518,12 @@
       *__fptr++ = '+';
     if (__flags & ios_base::showpoint)
       *__fptr++ = '#';
-    // As per [22.2.2.2.2.11]
-    if (__flags & ios_base::fixed || __prec > 0)
-      {
-	*__fptr++ = '.';
-	*__fptr++ = '*';
-	__incl_prec = true;
-      }
+
+    // As per DR 231: _always_, not only when 
+    // __flags & ios_base::fixed || __prec > 0
+    *__fptr++ = '.';
+    *__fptr++ = '*';
+
     if (__mod)
       *__fptr++ = __mod;
     ios_base::fmtflags __fltfield = __flags & ios_base::floatfield;
@@ -534,7 +535,6 @@
     else
       *__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g';
     *__fptr = '\0';
-    return __incl_prec;
   }
   
   void
diff -urN libstdc++-v3-orig/testsuite/22_locale/num_put_members_char.cc libstdc++-v3/testsuite/22_locale/num_put_members_char.cc
--- libstdc++-v3-orig/testsuite/22_locale/num_put_members_char.cc	2002-10-23 17:45:50.000000000 +0200
+++ libstdc++-v3/testsuite/22_locale/num_put_members_char.cc	2003-02-07 14:00:14.000000000 +0100
@@ -1,6 +1,6 @@
 // 2001-11-19 Benjamin Kosnik  <bkoz@redhat.com>
 
-// Copyright (C) 2001, 2002 Free Software Foundation
+// Copyright (C) 2001, 2002, 2003 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
@@ -363,6 +363,35 @@
   VERIFY( result == "0" );
 }
 
+// libstdc++/9548 and DR 231
+void test06()
+{
+  using namespace std;
+  bool test = true;
+
+  const locale loc_c = locale::classic();
+
+  ostringstream oss1, oss2;
+  oss1.imbue(loc_c);
+  oss2.imbue(loc_c);
+  const num_put<char>& np1 = use_facet<num_put<char> >(oss1.getloc());
+  const num_put<char>& np2 = use_facet<num_put<char> >(oss2.getloc());
+
+  string result1, result2;
+
+  oss1.precision(-1);
+  oss1.setf(ios_base::fixed, ios_base::floatfield);
+  np1.put(oss1.rdbuf(), oss1, '+', 30.5);
+  result1 = oss1.str();
+  VERIFY( result1 == "30.500000" );
+
+  oss2.precision(0);
+  oss2.setf(ios_base::scientific, ios_base::floatfield);
+  np2.put(oss2.rdbuf(), oss2, '+', 1.0);
+  result2 = oss2.str();
+  VERIFY( result2 == "1e+00" );
+}
+
 int main()
 {
   test01();
@@ -370,6 +399,7 @@
   test03();
   test04();
   test05();
+  test06();
   return 0;
 }
 
diff -urN libstdc++-v3-orig/testsuite/22_locale/num_put_members_wchar_t.cc libstdc++-v3/testsuite/22_locale/num_put_members_wchar_t.cc
--- libstdc++-v3-orig/testsuite/22_locale/num_put_members_wchar_t.cc	2002-10-23 17:45:50.000000000 +0200
+++ libstdc++-v3/testsuite/22_locale/num_put_members_wchar_t.cc	2003-02-07 14:01:09.000000000 +0100
@@ -1,6 +1,6 @@
 // 2001-11-19 Benjamin Kosnik  <bkoz@redhat.com>
 
-// Copyright (C) 2001, 2002 Free Software Foundation
+// Copyright (C) 2001, 2002, 2003 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
@@ -362,6 +362,35 @@
   result = oss.str();
   VERIFY( result == L"0" );
 }
+
+// libstdc++/9548 and DR 231
+void test06()
+{
+  using namespace std;
+  bool test = true;
+
+  const locale loc_c = locale::classic();
+
+  wostringstream woss1, woss2;
+  woss1.imbue(loc_c);
+  woss2.imbue(loc_c);
+  const num_put<wchar_t>& np1 = use_facet<num_put<wchar_t> >(woss1.getloc());
+  const num_put<wchar_t>& np2 = use_facet<num_put<wchar_t> >(woss2.getloc());
+
+  wstring result1, result2;
+
+  woss1.precision(-1);
+  woss1.setf(ios_base::fixed, ios_base::floatfield);
+  np1.put(woss1.rdbuf(), woss1, '+', 30.5);
+  result1 = woss1.str();
+  VERIFY( result1 == L"30.500000" );
+
+  woss2.precision(0);
+  woss2.setf(ios_base::scientific, ios_base::floatfield);
+  np2.put(woss2.rdbuf(), woss2, '+', 1.0);
+  result2 = woss2.str();
+  VERIFY( result2 == L"1e+00" );
+}
 #endif
 
 int main()
@@ -372,6 +401,7 @@
   test03();
   test04();
   test05();
+  test06();
 #endif
   return 0;
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]