On 08/10/14 11:07 +0100, Jonathan Wakely wrote:
On 07/10/14 21:10 +0200, Andreas Schwab wrote:
That cannot work.  std::__convert_from_v always passes __prec before
__v, but the format is "%a".

Ah yes. I'm testing this fix now.

Committed.

I assume it was working for me because __convert_from_v("%a", 6, 272.)
happens to pass the double differently from the integer, and vsnprintf
looks for a double in the relevant register and ignores the integer
argument.


commit 543771e2db1642715854ae4bec81d803ca8e2e59
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Wed Oct 8 10:39:27 2014 +0100

        * include/bits/locale_facets.tcc (num_put::_M_insert_float): Do not
        pass precision when using hexfloat format.
        * src/c++98/locale_facets.cc (__num_base::_S_format_float): Always
        output precision if C99 hexfloat conversion specifiers not available.

diff --git a/libstdc++-v3/include/bits/locale_facets.tcc 
b/libstdc++-v3/include/bits/locale_facets.tcc
index cf12a08..88adc0d 100644
--- a/libstdc++-v3/include/bits/locale_facets.tcc
+++ b/libstdc++-v3/include/bits/locale_facets.tcc
@@ -988,20 +988,32 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL
        __num_base::_S_format_float(__io, __fbuf, __mod);

#ifdef _GLIBCXX_USE_C99
+       // Precision is always used except for hexfloat format.
+       const bool __use_prec =
+         (__io.flags() & ios_base::floatfield) != ios_base::floatfield;
+
        // First try a buffer perhaps big enough (most probably sufficient
        // for non-ios_base::fixed outputs)
        int __cs_size = __max_digits * 3;
        char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-       __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
-                                     __fbuf, __prec, __v);
+       if (__use_prec)
+         __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+                                       __fbuf, __prec, __v);
+       else
+         __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+                                       __fbuf, __v);

        // 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));
-           __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
-                                         __fbuf, __prec, __v);
+           if (__use_prec)
+             __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+                                           __fbuf, __prec, __v);
+           else
+             __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+                                           __fbuf, __v);
          }
#else
        // Consider the possibility of long ios_base::fixed outputs
diff --git a/libstdc++-v3/src/c++98/locale_facets.cc 
b/libstdc++-v3/src/c++98/locale_facets.cc
index 7ed04e6..b3ca5dc 100644
--- a/libstdc++-v3/src/c++98/locale_facets.cc
+++ b/libstdc++-v3/src/c++98/locale_facets.cc
@@ -71,7 +71,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

    ios_base::fmtflags __fltfield = __flags & ios_base::floatfield;

+#ifdef _GLIBCXX_USE_C99
+    // Precision is always used except for hexfloat format.
    if (__fltfield != (ios_base::fixed | ios_base::scientific))
+#endif
      {
        // As per DR 231: not only when __flags & ios_base::fixed || __prec > 0
        *__fptr++ = '.';

Reply via email to