[PATCH] libcxx + MingW: correct printout of long doubles

Yaron Keren yaron.keren at gmail.com
Fri Oct 4 13:06:18 PDT 2013


Long ago Microsoft had decided (
http://msdn.microsoft.com/en-us/library/9cx8xs15.aspx) to make the long
double type in Visual C++ same as double, 64 bit. This was an incredibly
stupid decision, at least for those of us who actually care about numeric

MingW, gcc-based port for Windows, had kept 80-bit long doubles and so does
clang. This is a good decision which enable using these compilers in
numeric code where 80 bit long doubles are required.

However, MingW uses the Microsoft runtime DLL msvcrt.dll. Here lies a
problem: while gcc creates 80 bits long doubles, the MS runtime accepts 64
bit long doubles only. The problem is usually not obvious since the long
double is casted to a double, as in:


where the 10.0L will be silently cast to 10.0 and the routine will seem to

However, in the *printf and *scanf family of functions arguments are not
downcasted from long double to double (float does cast to double). For
instance, naively compiling


with gcc or clang with the MingW runtime will print garbage results.

The MingW developers did develop a solution to the problem, namely
alternative __mingw_printf and __mingw_scanf family of functions that
accept long double 80 bit arguments properly.  In order to use the correct
rotuines, one has to


which is not the default in libc but it is defined in gcc libstdc++ library
header "os_defines.h" as default.

So, the first patch to make libcxx print long doubles is to define
__USE_MINGW_ANSI_STDIO in __config. This will get the *printf and *scanf
functions working back on long doubles at least when libcxx is #included
(not in programs which do not include it, of course).

However, it will not make std::cout<<long_double work correctly. Why?
std::cout calls do_put which uses snprintf_l and asprintf_l to actually do
the work.

asprintf_l is implemented to call vasprintf_l which calls MingW vasprintf
which can handle long doubles if __USE_MINGW_ANSI_STDIO is defined. OK.
snprintf_l however is #defined to _snprintf_l, a function from msvcrt.dll
which does not support 80 bit long doubles. Problem.

Therefore, the second part of the patch implements snprintf_l  function in
a way similar to the other functions in src/support/win32/locale_win32.cpp
and locale_win32.h, calling upon vsnprintf for which there is a MingW
correct version.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131004/909fb117/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mingw_long_double.diff
Type: application/octet-stream
Size: 2021 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131004/909fb117/attachment.obj>

More information about the cfe-commits mailing list