https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123167
Bug ID: 123167
Summary: to_chars(long double) produces rubbish with
-mlong-double-64
Product: gcc
Version: unknown
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: cassio.neri at gmail dot com
Target Milestone: ---
Let T be double or long double and x = T{1}/T{3}. Then, for x86-64 with
-mlong-double-64, successful calls to
to_chars(begin, end, x, chars_format::scientific);
produce 3.333333333333333e-01 for double and, due ABI/UB issues, for long
double the result varies across runs. I once got 5.1301514607137e-4937. (See
https://godbolt.org/z/aM9z94Kac)
The result for long double is wrong under all accounts but, more precisely, it
was expected to exactly match double's because, under -mlong-double-64, long
double is equivalent to double [1].
This is what happens. The logic to account for different long double formats is
in
src/libstdc++-v3/src/c++17/floating_to_chars.cc, particularly, in this bit:
if constexpr (LONG_DOUBLE_KIND == LDK_BINARY64
|| LONG_DOUBLE_KIND == LDK_UNSUPPORTED)
return __floating_to_chars_shortest(first, last,
static_cast<double>(value),
fmt);
else
return __floating_to_chars_shortest(first, last, value, fmt);
This is correct but, the value of LONG_DOUBLE_KIND is determined when
floating_to_chars.cc is compiled. When the user changes the format, it's too
late because the binary of libstdc++ has already set in stone the format of
long double that to_chars supports.
The logic above has to be moved to a file that's compiled by the user (ie the
header charconv). Moreover, floating_to_chars.cc must, somehow, be prepared to
receive whatever long double format the user chooses.
I'm working on a fix as part of my rewrite of to_chars based on Tejú Jaguá.
I'll also include a test which will refer to this report.
[1] https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mlong-double-64-2