libstdc++: Add std::from_chars for floating-point types
authorJonathan Wakely <jwakely@redhat.com>
Mon, 20 Jul 2020 22:49:27 +0000 (23:49 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Mon, 20 Jul 2020 22:49:27 +0000 (23:49 +0100)
commit932fbc868ad429167a3d4d5625aa9d6dc0b4506b
tree20d9a830d6cdb638248b986e5fdaafda86b7eeac
parente443d8213864ac337c29092d4767224f280d2062
libstdc++: Add std::from_chars for floating-point types

This adds the missing std::from_chars overloads for floating-point
types, as required for C++17 conformance.

The implementation is a hack and not intended to be used in the long
term. Rather than parsing the string directly, this determines the
initial portion of the string that matches the pattern determined by the
chars_format parameter, then creates a NTBS to be parsed by strtod (or
strtold or strtof).

Because creating a NTBS requires allocating memory, but std::from_chars
is noexcept, we need to be careful to minimise allocation. Even after
being careful, allocation failure is still possible, and so a
non-conforming std::no_more_memory error code might be returned.

Because strtod et al depend on the current locale, but std::from_chars
does not, we change the current thread's locale to "C" using newlocale
and uselocale before calling strtod, and restore it afterwards.

Because strtod doesn't have the equivalent of a std::chars_format
parameter, it has to examine the input to determine the format in use,
even though the std::from_chars code has already parsed it once (or
twice for large input strings!)

By replacing the use of strtod we could avoid allocation, avoid changing
locale, and use optimised code paths specific to each std::chars_format
case. We would also get more portable behaviour, rather than depending
on the presence of uselocale, and on any bugs or quirks of the target
libc's strtod. Replacing strtod is a project for a later date.

libstdc++-v3/ChangeLog:

* acinclude.m4 (libtool_VERSION): Bump version.
* config.h.in: Regenerate.
* config/abi/pre/gnu.ver: Add GLIBCXX_3.4.29 version and new
exports.
* config/os/gnu-linux/ldbl-extra.ver: Add _GLIBCXX_LDBL_3.4.29
version and new export.
* configure: Regenerate.
* configure.ac: Check for <xlocale.h> and uselocale.
* crossconfig.m4: Add macro or checks for uselocale.
* include/std/charconv (from_chars): Declare overloads for
float, double, and long double.
* src/c++17/Makefile.am: Add new file.
* src/c++17/Makefile.in: Regenerate.
* src/c++17/floating_from_chars.cc: New file.
(from_chars): Define for float, double, and long double.
* testsuite/20_util/from_chars/1_c++20_neg.cc: Prune extra
diagnostics caused by new overloads.
* testsuite/20_util/from_chars/1_neg.cc: Likewise.
* testsuite/20_util/from_chars/2.cc: Check leading '+'.
* testsuite/20_util/from_chars/4.cc: New test.
* testsuite/20_util/from_chars/5.cc: New test.
* testsuite/util/testsuite_abi.cc: Add new symbol versions.
17 files changed:
libstdc++-v3/acinclude.m4
libstdc++-v3/config.h.in
libstdc++-v3/config/abi/pre/gnu.ver
libstdc++-v3/config/os/gnu-linux/ldbl-extra.ver
libstdc++-v3/configure
libstdc++-v3/configure.ac
libstdc++-v3/crossconfig.m4
libstdc++-v3/include/std/charconv
libstdc++-v3/src/c++17/Makefile.am
libstdc++-v3/src/c++17/Makefile.in
libstdc++-v3/src/c++17/floating_from_chars.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/from_chars/1_c++20_neg.cc
libstdc++-v3/testsuite/20_util/from_chars/1_neg.cc
libstdc++-v3/testsuite/20_util/from_chars/2.cc
libstdc++-v3/testsuite/20_util/from_chars/4.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/from_chars/5.cc [new file with mode: 0644]
libstdc++-v3/testsuite/util/testsuite_abi.cc