Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libcxx][libc] Hand in Hand PoC with from_chars #91651

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions libc/shared/fp_bits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Floating point number utils -----------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SHARED_FP_BITS_H
#define LLVM_LIBC_SHARED_FP_BITS_H

#include "src/__support/FPUtil/FPBits.h"

namespace LIBC_NAMESPACE_DECL {
namespace shared {

using fputil::FPBits;

} // namespace shared
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SHARED_FP_BITS_H
27 changes: 27 additions & 0 deletions libc/shared/str_to_float.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===-- String to float conversion utils ------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SHARED_STR_TO_FLOAT_H
#define LLVM_LIBC_SHARED_STR_TO_FLOAT_H

#include "src/__support/str_to_float.h"

namespace LIBC_NAMESPACE_DECL {
namespace shared {

using internal::ExpandedFloat;
using internal::FloatConvertReturn;
using internal::RoundDirection;
michaelrj-google marked this conversation as resolved.
Show resolved Hide resolved

using internal::binary_exp_to_float;
using internal::decimal_exp_to_float;

} // namespace shared
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SHARED_STR_TO_FLOAT_H
24 changes: 24 additions & 0 deletions libc/shared/str_to_integer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===-- String to int conversion utils --------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SHARED_STR_TO_INTEGER_H
#define LLVM_LIBC_SHARED_STR_TO_INTEGER_H

#include "src/__support/str_to_integer.h"

namespace LIBC_NAMESPACE_DECL {
namespace shared {

using LIBC_NAMESPACE::StrToNumResult;

using internal::strtointeger;

} // namespace shared
} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SHARED_STR_TO_INTEGER_H
12 changes: 12 additions & 0 deletions libc/src/__support/FPUtil/FPBits.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
//
//===----------------------------------------------------------------------===//

// -----------------------------------------------------------------------------
// **** WARNING ****
// This file is shared with libc++. You should also be careful when adding
// dependencies to this file, since it needs to build for all libc++ targets.
// -----------------------------------------------------------------------------

#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FPBITS_H

Expand Down Expand Up @@ -795,6 +801,12 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
static_assert(cpp::always_false<UnqualT>, "Unsupported type");
}

// -----------------------------------------------------------------------------
// **** WARNING ****
// This interface is shared with libc++, if you change this interface you need
// to update it in both libc and libc++. You should also be careful when adding
// dependencies to this file, since it needs to build for all libc++ targets.
// -----------------------------------------------------------------------------
// A generic class to manipulate C++ floating point formats.
// It derives its functionality to FPRepImpl above.
template <typename T>
Expand Down
11 changes: 11 additions & 0 deletions libc/src/__support/high_precision_decimal.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
//
//===----------------------------------------------------------------------===//

// -----------------------------------------------------------------------------
// **** WARNING ****
// This file is shared with libc++. You should also be careful when adding
// dependencies to this file, since it needs to build for all libc++ targets.
// -----------------------------------------------------------------------------

#ifndef LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H
#define LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H

Expand All @@ -23,6 +29,11 @@ struct LShiftTableEntry {
char const *power_of_five;
};

// -----------------------------------------------------------------------------
// **** WARNING ****
// This interface is shared with libc++, if you change this interface you need
// to update it in both libc and libc++.
// -----------------------------------------------------------------------------
// This is used in both this file and in the main str_to_float.h.
// TODO: Figure out where to put this.
enum class RoundDirection { Up, Down, Nearest };
Expand Down
26 changes: 26 additions & 0 deletions libc/src/__support/str_to_float.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
//
//===----------------------------------------------------------------------===//

// -----------------------------------------------------------------------------
// **** WARNING ****
// This file is shared with libc++. You should also be careful when adding
// dependencies to this file, since it needs to build for all libc++ targets.
// -----------------------------------------------------------------------------

#ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H
#define LLVM_LIBC_SRC___SUPPORT_STR_TO_FLOAT_H

Expand All @@ -32,11 +38,21 @@
namespace LIBC_NAMESPACE_DECL {
namespace internal {

// -----------------------------------------------------------------------------
// **** WARNING ****
// This interface is shared with libc++, if you change this interface you need
// to update it in both libc and libc++.
// -----------------------------------------------------------------------------
template <class T> struct ExpandedFloat {
typename fputil::FPBits<T>::StorageType mantissa;
int32_t exponent;
};

// -----------------------------------------------------------------------------
// **** WARNING ****
// This interface is shared with libc++, if you change this interface you need
// to update it in both libc and libc++.
// -----------------------------------------------------------------------------
template <class T> struct FloatConvertReturn {
ExpandedFloat<T> num = {0, 0};
int error = 0;
Expand Down Expand Up @@ -637,6 +653,11 @@ template <> LIBC_INLINE constexpr int32_t get_lower_bound<double>() {
return -(309 + 15 + 20);
}

// -----------------------------------------------------------------------------
// **** WARNING ****
// This interface is shared with libc++, if you change this interface you need
// to update it in both libc and libc++.
// -----------------------------------------------------------------------------
// Takes a mantissa and base 10 exponent and converts it into its closest
// floating point type T equivalient. First we try the Eisel-Lemire algorithm,
// then if that fails then we fall back to a more accurate algorithm for
Expand Down Expand Up @@ -716,6 +737,11 @@ LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float(
return output;
}

// -----------------------------------------------------------------------------
// **** WARNING ****
// This interface is shared with libc++, if you change this interface you need
// to update it in both libc and libc++.
// -----------------------------------------------------------------------------
// Takes a mantissa and base 2 exponent and converts it into its closest
// floating point type T equivalient. Since the exponent is already in the right
// form, this is mostly just shifting and rounding. This is used for hexadecimal
Expand Down
11 changes: 11 additions & 0 deletions libc/src/__support/str_to_integer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
//
//===----------------------------------------------------------------------===//

// -----------------------------------------------------------------------------
// **** WARNING ****
// This file is shared with libc++. You should also be careful when adding
// dependencies to this file, since it needs to build for all libc++ targets.
// -----------------------------------------------------------------------------

#ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H
#define LLVM_LIBC_SRC___SUPPORT_STR_TO_INTEGER_H

Expand Down Expand Up @@ -73,6 +79,11 @@ LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) {
return 10;
}

// -----------------------------------------------------------------------------
// **** WARNING ****
// This interface is shared with libc++, if you change this interface you need
// to update it in both libc and libc++.
// -----------------------------------------------------------------------------
// Takes a pointer to a string and the base to convert to. This function is used
// as the backend for all of the string to int functions.
template <class T>
Expand Down
11 changes: 11 additions & 0 deletions libc/src/__support/str_to_num_result.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
//
//===----------------------------------------------------------------------===//

// -----------------------------------------------------------------------------
// **** WARNING ****
// This file is shared with libc++. You should also be careful when adding
// dependencies to this file, since it needs to build for all libc++ targets.
// -----------------------------------------------------------------------------

#ifndef LLVM_LIBC_SRC___SUPPORT_STR_TO_NUM_RESULT_H
#define LLVM_LIBC_SRC___SUPPORT_STR_TO_NUM_RESULT_H

Expand All @@ -16,6 +22,11 @@

namespace LIBC_NAMESPACE_DECL {

// -----------------------------------------------------------------------------
// **** WARNING ****
// This interface is shared with libc++, if you change this interface you need
// to update it in both libc and libc++.
// -----------------------------------------------------------------------------
template <typename T> struct StrToNumResult {
T value;
int error;
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx17Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"`P0394R4 <https://wg21.link/P0394R4>`__","Hotel Parallelifornia: terminate() for Parallel Algorithms Exception Handling","2016-06 (Oulu)","|Complete|","17.0",""
"","","","","",""
"`P0003R5 <https://wg21.link/P0003R5>`__","Removing Deprecated Exception Specifications from C++17","2016-11 (Issaquah)","|Complete|","5.0",""
"`P0067R5 <https://wg21.link/P0067R5>`__","Elementary string conversions, revision 5","2016-11 (Issaquah)","|Partial|","","``std::(to|from)_chars`` for integrals has been available since version 7.0. ``std::to_chars`` for ``float`` and ``double`` since version 14.0 ``std::to_chars`` for ``long double`` uses the implementation for ``double``."
"`P0067R5 <https://wg21.link/P0067R5>`__","Elementary string conversions, revision 5","2016-11 (Issaquah)","|Partial|","","``std::(to|from)_chars`` for integrals has been available since version 7.0. ``std::to_chars`` for ``float`` and ``double`` since version 14.0 ``std::to_chars`` for ``long double`` uses the implementation for ``double``. ``std::from_chars`` for ``float`` and ``double`` since version 20.0."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reattaching my suggestion (clarify what's done resp. still open) after the table format changed to include notes.

Suggested change
"`P0067R5 <https://wg21.link/P0067R5>`__","Elementary string conversions, revision 5","2016-11 (Issaquah)","|Partial|","","``std::(to|from)_chars`` for integrals has been available since version 7.0. ``std::to_chars`` for ``float`` and ``double`` since version 14.0 ``std::to_chars`` for ``long double`` uses the implementation for ``double``. ``std::from_chars`` for ``float`` and ``double`` since version 20.0."
"`P0067R5 <https://wg21.link/P0067R5>`__","Elementary string conversions, revision 5","2016-11 (Issaquah)","|Partial|","","For integer types, ``std::(to|from)_chars`` has been available since version 7.0; for ``float`` and ``double``, ``std::to_chars`` since version 14.0 and ``std::from_chars`` since version 20.1. Support is complete except for ``long double``, which currently uses the implementation for ``double``.

"`P0403R1 <https://wg21.link/P0403R1>`__","Literal suffixes for ``basic_string_view``\ ","2016-11 (Issaquah)","|Complete|","4.0",""
"`P0414R2 <https://wg21.link/P0414R2>`__","Merging shared_ptr changes from Library Fundamentals to C++17","2016-11 (Issaquah)","|Complete|","11.0",""
"`P0418R2 <https://wg21.link/P0418R2>`__","Fail or succeed: there is no atomic lattice","2016-11 (Issaquah)","","",""
Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/Status/Cxx2cIssues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,5 @@
"","","","","",""
"`LWG3343 <https://wg21.link/LWG3343>`__","Ordering of calls to ``unlock()`` and ``notify_all()`` in Effects element of ``notify_all_at_thread_exit()`` should be reversed","Not Adopted Yet","|Complete|","16.0",""
"`LWG4139 <https://wg21.link/LWG4139>`__","§[time.zone.leap] recursive constraint in <=>","Not Adopted Yet","|Complete|","20.0",""
"`LWG3456 <https://wg21.link/LWG3456>`__","Pattern used by std::from_chars is underspecified (option B)",,"Not Yet Adopted","|Complete|","20.0",""
"","","","","",""
1 change: 1 addition & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ set(files
__bit/rotate.h
__bit_reference
__charconv/chars_format.h
__charconv/from_chars_floating_point.h
__charconv/from_chars_integral.h
__charconv/from_chars_result.h
__charconv/tables.h
Expand Down
72 changes: 72 additions & 0 deletions libcxx/include/__charconv/from_chars_floating_point.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// -*- C++ -*-
ldionne marked this conversation as resolved.
Show resolved Hide resolved
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___CHARCONV_FROM_CHARS_FLOATING_POINT_H
#define _LIBCPP___CHARCONV_FROM_CHARS_FLOATING_POINT_H

#include <__assert>
#include <__charconv/chars_format.h>
#include <__charconv/from_chars_result.h>
#include <__config>
#include <cstddef>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 17

template <class _Fp>
struct __from_chars_result {
_Fp __value;
ptrdiff_t __n;
errc __ec;
};

template <class _Fp>
_LIBCPP_EXPORTED_FROM_ABI [[gnu::pure]] __from_chars_result<_Fp> __from_chars_floating_point(
[[clang::noescape]] const char* __first, [[clang::noescape]] const char* __last, chars_format __fmt);

extern template __from_chars_result<float> __from_chars_floating_point(
[[clang::noescape]] const char* __first, [[clang::noescape]] const char* __last, chars_format __fmt);

extern template __from_chars_result<double> __from_chars_floating_point(
[[clang::noescape]] const char* __first, [[clang::noescape]] const char* __last, chars_format __fmt);
Comment on lines +37 to +45
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works, but FWIW it would be strictly simpler to use

_LIBCPP_EXPORTED_FROM_ABI __from_chars_result<float> __from_chars_float(...);
_LIBCPP_EXPORTED_FROM_ABI __from_chars_result<double> __from_chars_double(...);

That way, no need to think about whether the EXPORTED_FROM_ABI attribute is inherited by the external template declaration. It also simplifies the .cpp file since you don't need any explicit template instantiation. It's less "cute", but it's simpler overall.


template <class _Fp>
_LIBCPP_HIDE_FROM_ABI from_chars_result
__from_chars(const char* __first, const char* __last, _Fp& __value, chars_format __fmt) {
__from_chars_result __r = std::__from_chars_floating_point<_Fp>(__first, __last, __fmt);
if (__r.__ec != errc::invalid_argument)
__value = __r.__value;
return {__first + __r.__n, __r.__ec};
}

_LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_HIDE_FROM_ABI inline from_chars_result
from_chars(const char* __first, const char* __last, float& __value, chars_format __fmt = chars_format::general) {
return __from_chars(__first, __last, __value, __fmt);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be std::__from_chars, but personally I'd inline the body of __from_chars here to call std::__from_chars_float and std::__from_chars_double directly.

}

_LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_HIDE_FROM_ABI inline from_chars_result
from_chars(const char* __first, const char* __last, double& __value, chars_format __fmt = chars_format::general) {
return __from_chars(__first, __last, __value, __fmt);
}

#endif // _LIBCPP_STD_VER >= 17

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___CHARCONV_FROM_CHARS_FLOATING_POINT_H
13 changes: 13 additions & 0 deletions libcxx/include/__configuration/availability.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@
// in all versions of the library are available.
#if defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS)

# define _LIBCPP_INTRODUCED_IN_LLVM_20 1
# define _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE /* nothing */

# define _LIBCPP_INTRODUCED_IN_LLVM_19 1
# define _LIBCPP_INTRODUCED_IN_LLVM_19_ATTRIBUTE /* nothing */

Expand Down Expand Up @@ -132,6 +135,11 @@

// clang-format off

// LLVM 20
// TODO: Fill this in
# define _LIBCPP_INTRODUCED_IN_LLVM_20 0
# define _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE __attribute__((unavailable))

// LLVM 19
// TODO: Fill this in
# define _LIBCPP_INTRODUCED_IN_LLVM_19 0
Expand Down Expand Up @@ -409,6 +417,11 @@
#define _LIBCPP_AVAILABILITY_HAS_BAD_EXPECTED_ACCESS_KEY_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_19
#define _LIBCPP_AVAILABILITY_BAD_EXPECTED_ACCESS_KEY_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_19_ATTRIBUTE

// This controls the availability of floating-point std::from_chars functions.
// These overloads were added later than the integer overloads.
#define _LIBCPP_AVAILABILITY_HAS_FROM_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_20
#define _LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE

// Define availability attributes that depend on _LIBCPP_HAS_EXCEPTIONS.
// Those are defined in terms of the availability attributes above, and
// should not be vendor-specific.
Expand Down
7 changes: 7 additions & 0 deletions libcxx/include/charconv
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ namespace std {
constexpr from_chars_result from_chars(const char* first, const char* last,
see below& value, int base = 10); // constexpr since C++23

from_chars_result from_chars(const char* first, const char* last,
float& value, chars_format fmt);

from_chars_result from_chars(const char* first, const char* last,
double& value, chars_format fmt);

} // namespace std

*/
Expand All @@ -73,6 +79,7 @@ namespace std {

michaelrj-google marked this conversation as resolved.
Show resolved Hide resolved
#if _LIBCPP_STD_VER >= 17
# include <__charconv/chars_format.h>
# include <__charconv/from_chars_floating_point.h>
# include <__charconv/from_chars_integral.h>
# include <__charconv/from_chars_result.h>
# include <__charconv/tables.h>
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,7 @@ module std [system] {

module charconv {
module chars_format { header "__charconv/chars_format.h" }
module from_chars_floating_point { header "__charconv/from_chars_floating_point.h" }
module from_chars_integral { header "__charconv/from_chars_integral.h" }
module from_chars_result { header "__charconv/from_chars_result.h" }
module tables { header "__charconv/tables.h" }
Expand Down
Loading
Loading