authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-08-03 12:46:11+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-08-31 23:09:46+02:00
logf5e21e706bea3edb112ebcfdbfd4d4dd35082137
treee9024bb8bbf14fd143f12568c6778872ee91c9d6
parent619fd6c518c3d5a9f7189de479532526f253c805
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

llvm-libc: update to LLVM 23


45 files changed, 1206 insertions(+), 458 deletions(-)

lib/libcxx/libc/hdr/errno_macros.h+1-1
......@@ -25,6 +25,6 @@
2525
2626#include <errno.h>
2727
28#endif // LLVM_LIBC_FULL_BUILD
28#endif // LIBC_FULL_BUILD
2929
3030#endif // LLVM_LIBC_HDR_ERRNO_MACROS_H
lib/libcxx/libc/hdr/fenv_macros.h+1-1
......@@ -56,6 +56,6 @@
5656#define FE_UPWARD 0x800
5757#endif // FE_UPWARD
5858
59#endif // LLVM_LIBC_FULL_BUILD
59#endif // LIBC_FULL_BUILD
6060
6161#endif // LLVM_LIBC_HDR_FENV_MACROS_H
lib/libcxx/libc/hdr/float_macros.h+1-1
......@@ -17,6 +17,6 @@
1717
1818#include <float.h>
1919
20#endif // LLVM_LIBC_FULL_BUILD
20#endif // LIBC_FULL_BUILD
2121
2222#endif // LLVM_LIBC_HDR_FLOAT_MACROS_H
lib/libcxx/libc/hdr/limits_macros.h+1-1
......@@ -17,6 +17,6 @@
1717
1818#include <limits.h>
1919
20#endif // LLVM_LIBC_FULL_BUILD
20#endif // LIBC_FULL_BUILD
2121
2222#endif // LLVM_LIBC_HDR_LIMITS_MACROS_H
lib/libcxx/libc/hdr/types/size_t.h created+23
......@@ -0,0 +1,23 @@
1//===-- Proxy for size_t --------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8#ifndef LLVM_LIBC_HDR_TYPES_SIZE_T_H
9#define LLVM_LIBC_HDR_TYPES_SIZE_T_H
10
11#ifdef LIBC_FULL_BUILD
12
13#include "include/llvm-libc-types/size_t.h"
14
15#else
16
17#define __need_size_t
18#include <stddef.h>
19#undef __need_size_t
20
21#endif // LIBC_FULL_BUILD
22
23#endif // LLVM_LIBC_HDR_TYPES_SIZE_T_H
lib/libcxx/libc/hdr/types/wchar_t.h+1-1
......@@ -18,6 +18,6 @@
1818
1919#include "hdr/wchar_overlay.h"
2020
21#endif // LLVM_LIBC_FULL_BUILD
21#endif // LIBC_FULL_BUILD
2222
2323#endif // LLVM_LIBC_HDR_TYPES_WCHAR_T_H
lib/libcxx/libc/hdr/types/wint_t.h created+23
......@@ -0,0 +1,23 @@
1//===-- Definition of wint_t.h --------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_LIBC_HDR_TYPES_WINT_T_H
11#define LLVM_LIBC_HDR_TYPES_WINT_T_H
12
13#ifdef LIBC_FULL_BUILD
14
15#include "include/llvm-libc-types/wint_t.h"
16
17#else // overlay mode
18
19#include "hdr/wchar_overlay.h"
20
21#endif // LIBC_FULL_BUILD
22
23#endif // LLVM_LIBC_HDR_TYPES_WINT_T_H
lib/libcxx/libc/include/llvm-libc-macros/cfloat128-macros.h+1-1
......@@ -27,7 +27,7 @@
2727#define LIBC_TYPES_HAS_CFLOAT128
2828#endif
2929#elif defined(__GNUC__)
30#if (defined(__STDC_IEC_60559_COMPLEX__) || defined(__SIZEOF_FLOAT128__)) && \
30#if (defined(__STDC_IEC_60559_COMPLEX__) && defined(__SIZEOF_FLOAT128__)) && \
3131 (__GNUC__ >= 13 || (!defined(__cplusplus)))
3232#define LIBC_TYPES_HAS_CFLOAT128
3333#endif
lib/libcxx/libc/include/llvm-libc-macros/float-macros.h+6
......@@ -9,6 +9,12 @@
99#ifndef LLVM_LIBC_MACROS_FLOAT_MACROS_H
1010#define LLVM_LIBC_MACROS_FLOAT_MACROS_H
1111
12// __has_builtin is a Clang extension; GCC < 10 doesn't define it, which
13// turns a bare `#if __has_builtin(...)` into a preprocessor syntax error.
14#ifndef __has_builtin
15#define __has_builtin(x) 0
16#endif
17
1218#ifndef FLT_RADIX
1319#define FLT_RADIX __FLT_RADIX__
1420#endif // FLT_RADIX
lib/libcxx/libc/include/llvm-libc-macros/float16-macros.h+2-1
......@@ -12,7 +12,8 @@
1212#include "../llvm-libc-types/float128.h"
1313
1414#if defined(__FLT16_MANT_DIG__) && \
15 (!defined(__GNUC__) || __GNUC__ >= 13 || defined(__clang__)) && \
15 (!defined(__GNUC__) || __GNUC__ >= 13 || \
16 (defined(__clang__) && __clang_major__ >= 12)) && \
1617 !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \
1718 !defined(_WIN32)
1819#define LIBC_TYPES_HAS_FLOAT16
lib/libcxx/libc/include/llvm-libc-macros/stdfix-macros.h+1-1
......@@ -9,7 +9,7 @@
99#ifndef LLVM_LIBC_MACROS_STDFIX_MACROS_H
1010#define LLVM_LIBC_MACROS_STDFIX_MACROS_H
1111
12#ifdef __FRACT_FBIT__
12#if defined(__FRACT_FBIT__) && defined(__clang__)
1313// _Fract and _Accum types are available
1414#define LIBC_COMPILER_HAS_FIXED_POINT
1515#endif // __FRACT_FBIT__
lib/libcxx/libc/include/llvm-libc-types/size_t.h created+14
......@@ -0,0 +1,14 @@
1//===-- Definition of size_t types ----------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_TYPES_SIZE_T_H
10#define LLVM_LIBC_TYPES_SIZE_T_H
11
12typedef __SIZE_TYPE__ size_t;
13
14#endif // LLVM_LIBC_TYPES_SIZE_T_H
lib/libcxx/libc/src/__support/CPP/bit.h+46-14
......@@ -6,7 +6,7 @@
66//
77//===----------------------------------------------------------------------===//
88// This is inspired by LLVM ADT/bit.h header.
9// Some functions are missing, we can add them as needed (popcount, byteswap).
9// Some functions are missing, we can add them as needed.
1010
1111#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
1212#define LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
......@@ -27,9 +27,14 @@ namespace cpp {
2727#endif
2828
2929template <unsigned N>
30LIBC_INLINE static void inline_copy(const char *from, char *to) {
31#if __has_builtin(__builtin_memcpy_inline)
32 __builtin_memcpy_inline(to, from, N);
30LIBC_INLINE constexpr void inline_copy(const char *from, char *to) {
31#if __has_builtin(__builtin_memcpy_inline) && \
32 defined(LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
33 if (cpp::is_constant_evaluated())
34 for (unsigned i = 0; i < N; ++i)
35 to[i] = from[i];
36 else
37 __builtin_memcpy_inline(to, from, N);
3338#else
3439 for (unsigned i = 0; i < N; ++i)
3540 to[i] = from[i];
......@@ -39,15 +44,14 @@ LIBC_INLINE static void inline_copy(const char *from, char *to) {
3944// This implementation of bit_cast requires trivially-constructible To, to avoid
4045// UB in the implementation.
4146template <typename To, typename From>
42LIBC_INLINE constexpr cpp::enable_if_t<
47LIBC_INLINE static constexpr cpp::enable_if_t<
4348 (sizeof(To) == sizeof(From)) &&
4449 cpp::is_trivially_constructible<To>::value &&
4550 cpp::is_trivially_copyable<To>::value &&
4651 cpp::is_trivially_copyable<From>::value,
4752 To>
4853bit_cast(const From &from) {
49 MSAN_UNPOISON(&from, sizeof(From));
50#if __has_builtin(__builtin_bit_cast) || defined(LIBC_COMPILER_IS_MSVC)
54#if LIBC_HAS_BUILTIN_BIT_CAST
5155 return __builtin_bit_cast(To, from);
5256#else
5357 To to{};
......@@ -60,14 +64,12 @@ bit_cast(const From &from) {
6064
6165// The following simple bit copy from a smaller type to maybe-larger type.
6266template <typename To, typename From>
63LIBC_INLINE constexpr cpp::enable_if_t<
64 (sizeof(To) >= sizeof(From)) &&
65 cpp::is_trivially_constructible<To>::value &&
66 cpp::is_trivially_copyable<To>::value &&
67 cpp::is_trivially_copyable<From>::value,
68 void>
67LIBC_INLINE cpp::enable_if_t<(sizeof(To) >= sizeof(From)) &&
68 cpp::is_trivially_constructible<To>::value &&
69 cpp::is_trivially_copyable<To>::value &&
70 cpp::is_trivially_copyable<From>::value,
71 void>
6972bit_copy(const From &from, To &to) {
70 MSAN_UNPOISON(&from, sizeof(From));
7173 char *dst = reinterpret_cast<char *>(&to);
7274 const char *src = reinterpret_cast<const char *>(&from);
7375 inline_copy<sizeof(From)>(src, dst);
......@@ -330,6 +332,36 @@ ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll)
330332#endif // __builtin_popcountg
331333#undef ADD_SPECIALIZATION
332334
335/// Reverses the bytes in the given integer value.
336///
337/// All integral types are allowed, matching C++23 std::byteswap semantics.
338/// Signed types delegate to the unsigned path via static_cast.
339///
340/// The recursive decomposition generates optimal 'bswap' or 'rolw'
341/// instructions on Clang at -O2 without requiring compiler intrinsics.
342template <typename T>
343[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_integral_v<T>, T>
344byteswap(T value) {
345 static_assert(sizeof(T) <= 16, "byteswap: unsupported type size");
346 if constexpr (!cpp::is_unsigned_v<T>) {
347 using U = cpp::make_unsigned_t<T>;
348 return static_cast<T>(byteswap(static_cast<U>(value)));
349 } else if constexpr (sizeof(T) == 1) {
350 return value;
351 } else {
352 constexpr unsigned half_bits = sizeof(T) * 8 / 2;
353 using Half = cpp::conditional_t<
354 sizeof(T) == 2, uint8_t,
355 cpp::conditional_t<
356 sizeof(T) == 4, uint16_t,
357 cpp::conditional_t<sizeof(T) == 8, uint32_t, uint64_t>>>;
358 Half lo = static_cast<Half>(value);
359 Half hi = static_cast<Half>(value >> half_bits);
360 return static_cast<T>((static_cast<T>(byteswap(lo)) << half_bits) |
361 static_cast<T>(byteswap(hi)));
362 }
363}
364
333365} // namespace cpp
334366} // namespace LIBC_NAMESPACE_DECL
335367
lib/libcxx/libc/src/__support/CPP/iterator.h+29
......@@ -9,6 +9,7 @@
99#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H
1010#define LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H
1111
12#include "hdr/types/size_t.h"
1213#include "src/__support/CPP/type_traits/enable_if.h"
1314#include "src/__support/CPP/type_traits/is_convertible.h"
1415#include "src/__support/CPP/type_traits/is_same.h"
......@@ -18,9 +19,13 @@
1819namespace LIBC_NAMESPACE_DECL {
1920namespace cpp {
2021
22struct input_iterator_tag {};
23struct random_access_iterator_tag : input_iterator_tag {};
24
2125template <typename T> struct iterator_traits;
2226template <typename T> struct iterator_traits<T *> {
2327 using reference = T &;
28 using iterator_category = random_access_iterator_tag;
2429 using value_type = T;
2530};
2631
......@@ -93,6 +98,30 @@ public:
9398 }
9499};
95100
101namespace cpp_internal {
102
103template <typename It>
104LIBC_INLINE constexpr size_t distance(It first, It last,
105 random_access_iterator_tag) {
106 return last - first;
107}
108
109template <typename It>
110LIBC_INLINE constexpr auto distance(It first, It last, input_iterator_tag) {
111 size_t n = 0;
112 for (; first != last; ++first) {
113 ++n;
114 }
115 return n;
116}
117
118} // namespace cpp_internal
119
120template <typename It> LIBC_INLINE constexpr auto distance(It first, It last) {
121 return cpp_internal::distance(
122 first, last, typename iterator_traits<It>::iterator_category{});
123}
124
96125} // namespace cpp
97126} // namespace LIBC_NAMESPACE_DECL
98127
lib/libcxx/libc/src/__support/CPP/limits.h+26-62
......@@ -1,4 +1,4 @@
1//===-- A self contained equivalent of std::limits --------------*- C++ -*-===//
1//===-- A self contained equivalent of <limits> ----------------*- C++ -*-===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44// See https://llvm.org/LICENSE.txt for license information.
......@@ -13,78 +13,42 @@
1313#include "src/__support/CPP/type_traits/is_integral.h"
1414#include "src/__support/CPP/type_traits/is_signed.h"
1515#include "src/__support/macros/attributes.h" // LIBC_INLINE
16#include "src/__support/macros/config.h"
17#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128
1816
1917namespace LIBC_NAMESPACE_DECL {
2018namespace cpp {
2119
2220namespace internal {
2321
24template <typename T, T min_value, T max_value> struct integer_impl {
25 static_assert(cpp::is_integral_v<T>);
26 LIBC_INLINE static constexpr T max() { return max_value; }
27 LIBC_INLINE static constexpr T min() { return min_value; }
22template <typename T, bool is_integral> struct numeric_limits_impl {};
23
24template <typename T> struct numeric_limits_impl<T, true> {
25 LIBC_INLINE_VAR static constexpr bool is_signed = T(-1) < T(0);
26
2827 LIBC_INLINE_VAR static constexpr int digits =
29 CHAR_BIT * sizeof(T) - cpp::is_signed_v<T>;
28 (CHAR_BIT * sizeof(T)) - is_signed;
29
30 LIBC_INLINE static constexpr T min() {
31 if constexpr (is_signed) {
32 return T(T(1) << digits);
33 } else {
34 return 0;
35 }
36 }
37
38 LIBC_INLINE static constexpr T max() {
39 if constexpr (is_signed) {
40 return T(T(~0) ^ min());
41 } else {
42 return T(~0);
43 }
44 }
3045};
3146
3247} // namespace internal
3348
34template <class T> struct numeric_limits {};
35
36// TODO: Add numeric_limits specializations as needed for new types.
37template <>
38struct numeric_limits<short>
39 : public internal::integer_impl<short, SHRT_MIN, SHRT_MAX> {};
40
41template <>
42struct numeric_limits<unsigned short>
43 : public internal::integer_impl<unsigned short, 0, USHRT_MAX> {};
44
45template <>
46struct numeric_limits<int>
47 : public internal::integer_impl<int, INT_MIN, INT_MAX> {};
48
49template <>
50struct numeric_limits<unsigned int>
51 : public internal::integer_impl<unsigned int, 0, UINT_MAX> {};
52
53template <>
54struct numeric_limits<long>
55 : public internal::integer_impl<long, LONG_MIN, LONG_MAX> {};
56
57template <>
58struct numeric_limits<unsigned long>
59 : public internal::integer_impl<unsigned long, 0, ULONG_MAX> {};
60
61template <>
62struct numeric_limits<long long>
63 : public internal::integer_impl<long long, LLONG_MIN, LLONG_MAX> {};
64
65template <>
66struct numeric_limits<unsigned long long>
67 : public internal::integer_impl<unsigned long long, 0, ULLONG_MAX> {};
68
69template <>
70struct numeric_limits<char>
71 : public internal::integer_impl<char, CHAR_MIN, CHAR_MAX> {};
72
73template <>
74struct numeric_limits<signed char>
75 : public internal::integer_impl<signed char, SCHAR_MIN, SCHAR_MAX> {};
76
77template <>
78struct numeric_limits<unsigned char>
79 : public internal::integer_impl<unsigned char, 0, UCHAR_MAX> {};
80
81#ifdef LIBC_TYPES_HAS_INT128
82// On platform where UInt128 resolves to __uint128_t, this specialization
83// provides the limits of UInt128.
84template <>
85struct numeric_limits<__uint128_t>
86 : public internal::integer_impl<__uint128_t, 0, ~__uint128_t(0)> {};
87#endif
49template <typename T>
50struct numeric_limits
51 : public internal::numeric_limits_impl<T, is_integral_v<T>> {};
8852
8953} // namespace cpp
9054} // namespace LIBC_NAMESPACE_DECL
lib/libcxx/libc/src/__support/CPP/string_view.h+79-62
......@@ -18,46 +18,52 @@
1818namespace LIBC_NAMESPACE_DECL {
1919namespace cpp {
2020
21// This is very simple alternate of the std::string_view class. There is no
22// bounds check performed in any of the methods. The callers are expected to
23// do the checks before invoking the methods.
21template <typename CharT> class basic_string_view;
22
23using string_view = basic_string_view<char>;
24using wstring_view = basic_string_view<wchar_t>;
25
26// This is a very simple alternate of the std::basic_string_view class template.
27// There is no bounds check performed in any of the methods. The callers are
28// expected to do the checks before invoking the methods.
2429//
2530// This class will be extended as needed in future.
26class string_view {
31template <typename CharT> class basic_string_view {
2732private:
28 const char *Data;
33 const CharT *Data;
2934 size_t Len;
3035
31 LIBC_INLINE static size_t min(size_t A, size_t B) { return A <= B ? A : B; }
36 LIBC_INLINE static constexpr size_t min(size_t A, size_t B) {
37 return A <= B ? A : B;
38 }
3239
33 LIBC_INLINE static int compareMemory(const char *Lhs, const char *Rhs,
34 size_t Length) {
40 LIBC_INLINE static constexpr int compareN(const CharT *Lhs, const CharT *Rhs,
41 size_t Length) {
3542 for (size_t i = 0; i < Length; ++i)
36 if (int Diff = (int)Lhs[i] - (int)Rhs[i])
37 return Diff;
43 if (Lhs[i] != Rhs[i])
44 return Lhs[i] < Rhs[i] ? -1 : 1;
3845 return 0;
3946 }
4047
41 LIBC_INLINE static constexpr size_t length(const char *Str) {
42 for (const char *End = Str;; ++End)
43 if (*End == '\0')
48 LIBC_INLINE static constexpr size_t length(const CharT *Str) {
49 for (const CharT *End = Str;; ++End)
50 if (*End == CharT{0})
4451 return static_cast<size_t>(End - Str);
4552 }
4653
47 LIBC_INLINE bool equals(string_view Other) const {
48 return (Len == Other.Len &&
49 compareMemory(Data, Other.Data, Other.Len) == 0);
54 LIBC_INLINE constexpr bool equals(basic_string_view Other) const {
55 return (Len == Other.Len && compareN(Data, Other.Data, Other.Len) == 0);
5056 }
5157
5258public:
53 using value_type = char;
59 using value_type = CharT;
5460 using size_type = size_t;
5561 using difference_type = ptrdiff_t;
56 using pointer = char *;
57 using const_pointer = const char *;
58 using reference = char &;
59 using const_reference = const char &;
60 using const_iterator = char *;
62 using pointer = CharT *;
63 using const_pointer = const CharT *;
64 using reference = CharT &;
65 using const_reference = const CharT &;
66 using const_iterator = CharT *;
6167 using iterator = const_iterator;
6268
6369 // special value equal to the maximum value representable by the type
......@@ -65,124 +71,126 @@ public:
6571 LIBC_INLINE_VAR static constexpr size_t npos =
6672 cpp::numeric_limits<size_t>::max();
6773
68 LIBC_INLINE constexpr string_view() : Data(nullptr), Len(0) {}
74 LIBC_INLINE constexpr basic_string_view() : Data(nullptr), Len(0) {}
6975
7076 // Assumes Str is a null-terminated string. The length of the string does
7177 // not include the terminating null character.
7278 // Preconditions: [Str, Str + ​length(Str)) is a valid range.
73 LIBC_INLINE constexpr string_view(const char *Str)
79 LIBC_INLINE constexpr basic_string_view(const CharT *Str)
7480 : Data(Str), Len(length(Str)) {}
7581
7682 // Preconditions: [Str, Str + N) is a valid range.
77 LIBC_INLINE constexpr string_view(const char *Str, size_t N)
83 LIBC_INLINE constexpr basic_string_view(const CharT *Str, size_t N)
7884 : Data(Str), Len(N) {}
7985
80 LIBC_INLINE constexpr const char *data() const { return Data; }
86 LIBC_INLINE constexpr const CharT *data() const { return Data; }
8187
82 // Returns the size of the string_view.
88 // Returns the size of the basic_string_view.
8389 LIBC_INLINE constexpr size_t size() const { return Len; }
8490
85 // Returns whether the string_view is empty.
91 // Returns whether the basic_string_view is empty.
8692 LIBC_INLINE constexpr bool empty() const { return Len == 0; }
8793
8894 // Returns an iterator to the first character of the view.
89 LIBC_INLINE const char *begin() const { return Data; }
95 LIBC_INLINE constexpr const CharT *begin() const { return Data; }
9096
9197 // Returns an iterator to the character following the last character of the
9298 // view.
93 LIBC_INLINE const char *end() const { return Data + Len; }
99 LIBC_INLINE constexpr const CharT *end() const { return Data + Len; }
94100
95101 // Returns a const reference to the character at specified location pos.
96102 // No bounds checking is performed: the behavior is undefined if pos >=
97103 // size().
98 LIBC_INLINE constexpr const char &operator[](size_t Index) const {
104 LIBC_INLINE constexpr const CharT &operator[](size_t Index) const {
99105 return Data[Index];
100106 }
101107
102108 /// compare - Compare two strings; the result is -1, 0, or 1 if this string
103109 /// is lexicographically less than, equal to, or greater than the \p Other.
104 LIBC_INLINE int compare(string_view Other) const {
110 LIBC_INLINE constexpr int compare(basic_string_view Other) const {
105111 // Check the prefix for a mismatch.
106 if (int Res = compareMemory(Data, Other.Data, min(Len, Other.Len)))
107 return Res < 0 ? -1 : 1;
112 if (int Res = compareN(Data, Other.Data, min(Len, Other.Len)))
113 return Res;
108114 // Otherwise the prefixes match, so we only need to check the lengths.
109115 if (Len == Other.Len)
110116 return 0;
111117 return Len < Other.Len ? -1 : 1;
112118 }
113119
114 LIBC_INLINE bool operator==(string_view Other) const { return equals(Other); }
115 LIBC_INLINE bool operator!=(string_view Other) const {
120 LIBC_INLINE constexpr bool operator==(basic_string_view Other) const {
121 return equals(Other);
122 }
123 LIBC_INLINE constexpr bool operator!=(basic_string_view Other) const {
116124 return !(*this == Other);
117125 }
118 LIBC_INLINE bool operator<(string_view Other) const {
126 LIBC_INLINE constexpr bool operator<(basic_string_view Other) const {
119127 return compare(Other) == -1;
120128 }
121 LIBC_INLINE bool operator<=(string_view Other) const {
129 LIBC_INLINE constexpr bool operator<=(basic_string_view Other) const {
122130 return compare(Other) != 1;
123131 }
124 LIBC_INLINE bool operator>(string_view Other) const {
132 LIBC_INLINE constexpr bool operator>(basic_string_view Other) const {
125133 return compare(Other) == 1;
126134 }
127 LIBC_INLINE bool operator>=(string_view Other) const {
135 LIBC_INLINE constexpr bool operator>=(basic_string_view Other) const {
128136 return compare(Other) != -1;
129137 }
130138
131139 // Moves the start of the view forward by n characters.
132140 // The behavior is undefined if n > size().
133 LIBC_INLINE void remove_prefix(size_t N) {
141 LIBC_INLINE constexpr void remove_prefix(size_t N) {
134142 Len -= N;
135143 Data += N;
136144 }
137145
138146 // Moves the end of the view back by n characters.
139147 // The behavior is undefined if n > size().
140 LIBC_INLINE void remove_suffix(size_t N) { Len -= N; }
148 LIBC_INLINE constexpr void remove_suffix(size_t N) { Len -= N; }
141149
142150 // Check if this string starts with the given Prefix.
143 LIBC_INLINE bool starts_with(string_view Prefix) const {
144 return Len >= Prefix.Len &&
145 compareMemory(Data, Prefix.Data, Prefix.Len) == 0;
151 LIBC_INLINE constexpr bool starts_with(basic_string_view Prefix) const {
152 return Len >= Prefix.Len && compareN(Data, Prefix.Data, Prefix.Len) == 0;
146153 }
147154
148155 // Check if this string starts with the given Prefix.
149 LIBC_INLINE bool starts_with(const char Prefix) const {
156 LIBC_INLINE constexpr bool starts_with(const CharT Prefix) const {
150157 return !empty() && front() == Prefix;
151158 }
152159
153160 // Check if this string ends with the given Prefix.
154 LIBC_INLINE bool ends_with(const char Suffix) const {
161 LIBC_INLINE constexpr bool ends_with(const CharT Suffix) const {
155162 return !empty() && back() == Suffix;
156163 }
157164
158165 // Check if this string ends with the given Suffix.
159 LIBC_INLINE bool ends_with(string_view Suffix) const {
166 LIBC_INLINE constexpr bool ends_with(basic_string_view Suffix) const {
160167 return Len >= Suffix.Len &&
161 compareMemory(end() - Suffix.Len, Suffix.Data, Suffix.Len) == 0;
168 compareN(end() - Suffix.Len, Suffix.Data, Suffix.Len) == 0;
162169 }
163170
164171 // Return a reference to the substring from [Start, Start + N).
165172 //
166 // Start The index of the starting character in the substring; if the index is
167 // npos or greater than the length of the string then the empty substring will
168 // be returned.
173 // Start The index of the starting character in the substring; if the index
174 // is npos or greater than the length of the string then the empty substring
175 // will be returned.
169176 //
170177 // N The number of characters to included in the substring. If N exceeds the
171178 // number of characters remaining in the string, the string suffix (starting
172179 // with Start) will be returned.
173 LIBC_INLINE string_view substr(size_t Start, size_t N = npos) const {
180 LIBC_INLINE constexpr basic_string_view substr(size_t Start,
181 size_t N = npos) const {
174182 Start = min(Start, Len);
175 return string_view(Data + Start, min(N, Len - Start));
183 return basic_string_view(Data + Start, min(N, Len - Start));
176184 }
177185
178186 // front - Get the first character in the string.
179 LIBC_INLINE char front() const { return Data[0]; }
187 LIBC_INLINE constexpr CharT front() const { return Data[0]; }
180188
181189 // back - Get the last character in the string.
182 LIBC_INLINE char back() const { return Data[Len - 1]; }
190 LIBC_INLINE constexpr CharT back() const { return Data[Len - 1]; }
183191
184192 // Finds the first occurence of c in this view, starting at position From.
185 LIBC_INLINE constexpr size_t find_first_of(const char c,
193 LIBC_INLINE constexpr size_t find_first_of(const CharT c,
186194 size_t From = 0) const {
187195 for (size_t Pos = From; Pos < size(); ++Pos)
188196 if ((*this)[Pos] == c)
......@@ -191,7 +199,7 @@ public:
191199 }
192200
193201 // Finds the last occurence of c in this view, ending at position End.
194 LIBC_INLINE constexpr size_t find_last_of(const char c,
202 LIBC_INLINE constexpr size_t find_last_of(const CharT c,
195203 size_t End = npos) const {
196204 End = End >= size() ? size() : End + 1;
197205 for (; End > 0; --End)
......@@ -200,9 +208,18 @@ public:
200208 return npos;
201209 }
202210
203 // Finds the first character not equal to c in this view, starting at position
204 // From.
205 LIBC_INLINE constexpr size_t find_first_not_of(const char c,
211 LIBC_INLINE constexpr size_t find_last_not_of(const char c,
212 size_t end = npos) const {
213 end = end >= size() ? size() : end + 1;
214 for (; end > 0; --end)
215 if ((*this)[end - 1] != c)
216 return end - 1;
217 return npos;
218 }
219
220 // Finds the first character not equal to c in this view, starting at
221 // position From.
222 LIBC_INLINE constexpr size_t find_first_not_of(const CharT c,
206223 size_t From = 0) const {
207224 for (size_t Pos = From; Pos < size(); ++Pos)
208225 if ((*this)[Pos] != c)
......@@ -211,7 +228,7 @@ public:
211228 }
212229
213230 // Check if this view contains the given character.
214 LIBC_INLINE constexpr bool contains(char c) const {
231 LIBC_INLINE constexpr bool contains(CharT c) const {
215232 return find_first_of(c) != npos;
216233 }
217234};
lib/libcxx/libc/src/__support/CPP/type_traits/is_assignable.h created+63
......@@ -0,0 +1,63 @@
1//===------------------------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// \file
10// This file contains a free-standing implementation of is_assignable
11// type trait.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ASSIGNABLE_H
16#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ASSIGNABLE_H
17
18#include "src/__support/CPP/type_traits/bool_constant.h"
19#include "src/__support/CPP/utility/declval.h"
20#include "src/__support/macros/attributes.h"
21#include "src/__support/macros/config.h"
22
23namespace LIBC_NAMESPACE_DECL {
24namespace cpp {
25
26namespace is_assignable_detail {
27
28#if LIBC_HAS_BUILTIN_IS_ASSIGNABLE
29
30template <typename T, typename U>
31struct is_assignable_impl : public bool_constant<__is_assignable(T, U)> {};
32
33#else
34// Fallback SFINAE implementation for GCC 7 and older toolchains
35
36template <typename T, typename U> struct is_assignable_impl {
37private:
38 template <typename T1, typename U1>
39 LIBC_INLINE static auto test(int)
40 -> decltype(declval<T1>() = declval<U1>(), bool_constant<true>());
41
42 template <typename, typename>
43 LIBC_INLINE static auto test(...) -> bool_constant<false>;
44
45public:
46 using type = decltype(test<T, U>(0));
47};
48
49#endif // LIBC_HAS_BUILTIN_IS_ASSIGNABLE
50
51} // namespace is_assignable_detail
52
53// is_assignable
54template <typename T, typename U>
55struct is_assignable : public is_assignable_detail::is_assignable_impl<T, U> {};
56
57template <typename T, typename U>
58LIBC_INLINE_VAR constexpr bool is_assignable_v = is_assignable<T, U>::value;
59
60} // namespace cpp
61} // namespace LIBC_NAMESPACE_DECL
62
63#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_ASSIGNABLE_H
lib/libcxx/libc/src/__support/CPP/type_traits/is_constant_evaluated.h+4
......@@ -15,7 +15,11 @@ namespace LIBC_NAMESPACE_DECL {
1515namespace cpp {
1616
1717LIBC_INLINE constexpr bool is_constant_evaluated() {
18#if LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED
1819 return __builtin_is_constant_evaluated();
20#else
21 return false;
22#endif
1923}
2024
2125} // namespace cpp
lib/libcxx/libc/src/__support/CPP/type_traits/is_constructible.h created+65
......@@ -0,0 +1,65 @@
1//===------------------------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// \file
10// This file contains a free-standing implementation of is_constructible
11// type trait.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONSTRUCTIBLE_H
16#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONSTRUCTIBLE_H
17
18#include "src/__support/CPP/type_traits/bool_constant.h"
19#include "src/__support/CPP/utility/declval.h"
20#include "src/__support/macros/attributes.h"
21#include "src/__support/macros/config.h"
22
23namespace LIBC_NAMESPACE_DECL {
24namespace cpp {
25
26namespace is_contructible_detail {
27
28#if LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE
29
30template <typename T, typename... Args>
31struct is_constructible_impl
32 : public bool_constant<__is_constructible(T, Args...)> {};
33
34#else
35// Fallback SFINAE implementation for GCC 7 and older toolchains
36
37template <typename T, typename... Args> struct is_constructible_impl {
38private:
39 template <typename T1, typename... Args1>
40 LIBC_INLINE static auto test(int)
41 -> decltype(T1(declval<Args1>()...), bool_constant<true>());
42
43 template <typename, typename...>
44 LIBC_INLINE static auto test(...) -> bool_constant<false>;
45
46public:
47 using type = decltype(test<T, Args...>(0));
48};
49
50#endif // LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE
51
52} // namespace is_contructible_detail
53
54template <typename T, typename... Args>
55struct is_constructible
56 : public is_contructible_detail::is_constructible_impl<T, Args...> {};
57
58template <typename T, typename... Args>
59LIBC_INLINE_VAR constexpr bool is_constructible_v =
60 is_constructible<T, Args...>::value;
61
62} // namespace cpp
63} // namespace LIBC_NAMESPACE_DECL
64
65#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONSTRUCTIBLE_H
lib/libcxx/libc/src/__support/CPP/type_traits/is_copy_assignable.h+3-4
......@@ -9,7 +9,7 @@
99#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_ASSIGNABLE_H
1010
1111#include "src/__support/CPP/type_traits/add_lvalue_reference.h"
12#include "src/__support/CPP/type_traits/integral_constant.h"
12#include "src/__support/CPP/type_traits/is_assignable.h"
1313#include "src/__support/macros/config.h"
1414
1515namespace LIBC_NAMESPACE_DECL {
......@@ -18,9 +18,8 @@ namespace cpp {
1818// is copy assignable
1919template <class T>
2020struct is_copy_assignable
21 : public integral_constant<
22 bool, __is_assignable(cpp::add_lvalue_reference_t<T>,
23 cpp::add_lvalue_reference_t<const T>)> {};
21 : public cpp::is_assignable<cpp::add_lvalue_reference_t<T>,
22 cpp::add_lvalue_reference_t<const T>> {};
2423
2524template <class T>
2625LIBC_INLINE_VAR constexpr bool is_copy_assignable_v =
lib/libcxx/libc/src/__support/CPP/type_traits/is_copy_constructible.h+2-3
......@@ -9,7 +9,7 @@
99#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_COPY_CONSTRUCTIBLE_H
1010
1111#include "src/__support/CPP/type_traits/add_lvalue_reference.h"
12#include "src/__support/CPP/type_traits/integral_constant.h"
12#include "src/__support/CPP/type_traits/is_constructible.h"
1313#include "src/__support/macros/config.h"
1414
1515namespace LIBC_NAMESPACE_DECL {
......@@ -18,8 +18,7 @@ namespace cpp {
1818// is copy constructible
1919template <class T>
2020struct is_copy_constructible
21 : public integral_constant<
22 bool, __is_constructible(T, cpp::add_lvalue_reference_t<const T>)> {};
21 : public cpp::is_constructible<T, cpp::add_lvalue_reference_t<const T>> {};
2322
2423template <class T>
2524LIBC_INLINE_VAR constexpr bool is_copy_constructible_v =
lib/libcxx/libc/src/__support/CPP/type_traits/is_integral.h+10-5
......@@ -26,13 +26,18 @@ private:
2626 }
2727
2828public:
29 LIBC_INLINE_VAR static constexpr bool value = __is_unqualified_any_of<
30 T,
29 LIBC_INLINE_VAR static constexpr bool value =
30 __is_unqualified_any_of<T,
3131#ifdef LIBC_TYPES_HAS_INT128
32 __int128_t, __uint128_t,
32 __int128_t, __uint128_t,
3333#endif
34 char, signed char, unsigned char, short, unsigned short, int,
35 unsigned int, long, unsigned long, long long, unsigned long long, bool>();
34#ifdef __cpp_char8_t
35 char8_t,
36#endif
37 char16_t, char32_t, wchar_t, char, signed char,
38 unsigned char, short, unsigned short, int,
39 unsigned int, long, unsigned long, long long,
40 unsigned long long, bool>();
3641};
3742template <typename T>
3843LIBC_INLINE_VAR constexpr bool is_integral_v = is_integral<T>::value;
lib/libcxx/libc/src/__support/CPP/type_traits/is_move_assignable.h+3-4
......@@ -10,7 +10,7 @@
1010
1111#include "src/__support/CPP/type_traits/add_lvalue_reference.h"
1212#include "src/__support/CPP/type_traits/add_rvalue_reference.h"
13#include "src/__support/CPP/type_traits/integral_constant.h"
13#include "src/__support/CPP/type_traits/is_assignable.h"
1414#include "src/__support/macros/config.h"
1515
1616namespace LIBC_NAMESPACE_DECL {
......@@ -19,9 +19,8 @@ namespace cpp {
1919// is move assignable
2020template <class T>
2121struct is_move_assignable
22 : public integral_constant<bool, __is_assignable(
23 cpp::add_lvalue_reference_t<T>,
24 cpp::add_rvalue_reference_t<T>)> {};
22 : public cpp::is_assignable<cpp::add_lvalue_reference_t<T>,
23 cpp::add_rvalue_reference_t<T>> {};
2524
2625template <class T>
2726LIBC_INLINE_VAR constexpr bool is_move_assignable_v =
lib/libcxx/libc/src/__support/CPP/type_traits/is_move_constructible.h+2-3
......@@ -9,7 +9,7 @@
99#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_MOVE_CONSTRUCTIBLE_H
1010
1111#include "src/__support/CPP/type_traits/add_rvalue_reference.h"
12#include "src/__support/CPP/type_traits/integral_constant.h"
12#include "src/__support/CPP/type_traits/is_constructible.h"
1313#include "src/__support/macros/config.h"
1414
1515namespace LIBC_NAMESPACE_DECL {
......@@ -18,8 +18,7 @@ namespace cpp {
1818// is move constructible
1919template <class T>
2020struct is_move_constructible
21 : public integral_constant<bool, __is_constructible(
22 T, cpp::add_rvalue_reference_t<T>)> {};
21 : public cpp::is_constructible<T, cpp::add_rvalue_reference_t<T>> {};
2322
2423template <class T>
2524LIBC_INLINE_VAR constexpr bool is_move_constructible_v =
lib/libcxx/libc/src/__support/CPP/type_traits/is_unsigned.h+3-3
......@@ -10,7 +10,7 @@
1010
1111#include "include/llvm-libc-macros/stdfix-macros.h"
1212#include "src/__support/CPP/type_traits/bool_constant.h"
13#include "src/__support/CPP/type_traits/is_arithmetic.h"
13#include "src/__support/CPP/type_traits/is_integral.h"
1414#include "src/__support/CPP/type_traits/is_same.h"
1515#include "src/__support/CPP/type_traits/remove_cv.h"
1616#include "src/__support/macros/attributes.h"
......@@ -23,7 +23,7 @@ namespace cpp {
2323
2424#ifndef LIBC_COMPILER_HAS_FIXED_POINT
2525template <typename T>
26struct is_unsigned : bool_constant<(is_arithmetic_v<T> && (T(-1) > T(0)))> {
26struct is_unsigned : bool_constant<(is_integral_v<T> && (T(-1) > T(0)))> {
2727 LIBC_INLINE constexpr operator bool() const { return is_unsigned::value; }
2828 LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; }
2929};
......@@ -37,7 +37,7 @@ private:
3737
3838public:
3939 LIBC_INLINE_VAR static constexpr bool value =
40 (is_arithmetic_v<T> && (T(-1) > T(0))) ||
40 (is_integral_v<T> && (T(-1) > T(0))) ||
4141 __is_unqualified_any_of<T, unsigned short fract, unsigned fract,
4242 unsigned long fract, unsigned short accum,
4343 unsigned accum, unsigned long accum,
lib/libcxx/libc/src/__support/FPUtil/FPBits.h+16-13
......@@ -798,7 +798,9 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
798798 return FPType::IEEE754_Binary64;
799799 else if constexpr (LDBL_MANT_DIG == 64)
800800 return FPType::X86_Binary80;
801 else if constexpr (LDBL_MANT_DIG == 113)
801 // TODO: properly treat double-double type.
802 // else if constexpr (LDBL_MANT_DIG == 113)
803 else
802804 return FPType::IEEE754_Binary128;
803805 }
804806#if defined(LIBC_TYPES_HAS_FLOAT16)
......@@ -833,21 +835,22 @@ struct FPBits final : public internal::FPRepImpl<get_fp_type<T>(), FPBits<T>> {
833835 // Constructors.
834836 LIBC_INLINE constexpr FPBits() = default;
835837
836 template <typename XType> LIBC_INLINE constexpr explicit FPBits(XType x) {
837 using Unqual = typename cpp::remove_cv_t<XType>;
838 if constexpr (cpp::is_same_v<Unqual, T>) {
839 UP::bits = cpp::bit_cast<StorageType>(x);
840 } else if constexpr (cpp::is_same_v<Unqual, StorageType>) {
841 UP::bits = x;
842 } else {
843 // We don't want accidental type promotions/conversions, so we require
844 // exact type match.
845 static_assert(cpp::always_false<XType>);
846 }
838 template <
839 typename XType,
840 cpp::enable_if_t<cpp::is_same_v<cpp::remove_cv_t<XType>, T>, int> = 0>
841 LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR explicit FPBits(XType x) {
842 UP::bits = cpp::bit_cast<StorageType>(x);
847843 }
848844
845 template <typename XType,
846 cpp::enable_if_t<
847 cpp::is_same_v<cpp::remove_cv_t<XType>, StorageType>, int> = 0>
848 LIBC_INLINE constexpr explicit FPBits(XType x) : UP(x) {}
849
849850 // Floating-point conversions.
850 LIBC_INLINE constexpr T get_val() const { return cpp::bit_cast<T>(UP::bits); }
851 LIBC_INLINE LIBC_BIT_CAST_CONSTEXPR T get_val() const {
852 return cpp::bit_cast<T>(UP::bits);
853 }
851854};
852855
853856} // namespace fputil
lib/libcxx/libc/src/__support/FPUtil/rounding_mode.h+25-5
......@@ -24,8 +24,12 @@ namespace generic {
2424// 1.0f + 2^-25 = 1.0f for FE_TONEAREST, FE_DOWNWARD, FE_TOWARDZERO
2525// = 0x1.000002f for FE_UPWARD.
2626LIBC_INLINE bool fenv_is_round_up() {
27#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
28 return false;
29#else
2730 static volatile float x = 0x1.0p-25f;
2831 return (1.0f + x != 1.0f);
32#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
2933}
3034
3135// Quick free-standing test whether fegetround() == FE_DOWNWARD.
......@@ -33,8 +37,12 @@ LIBC_INLINE bool fenv_is_round_up() {
3337// -1.0f - 2^-25 = -1.0f for FE_TONEAREST, FE_UPWARD, FE_TOWARDZERO
3438// = -0x1.000002f for FE_DOWNWARD.
3539LIBC_INLINE bool fenv_is_round_down() {
40#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
41 return false;
42#else
3643 static volatile float x = 0x1.0p-25f;
3744 return (-1.0f - x != -1.0f);
45#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
3846}
3947
4048// Quick free-standing test whether fegetround() == FE_TONEAREST.
......@@ -44,9 +52,13 @@ LIBC_INLINE bool fenv_is_round_down() {
4452// 1.5f - 2^-24 = 1.5f for FE_TONEAREST, FE_UPWARD
4553// = 0x1.0ffffep-1f for FE_DOWNWARD, FE_TOWARDZERO
4654LIBC_INLINE bool fenv_is_round_to_nearest() {
55#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
56 return true;
57#else
4758 static volatile float x = 0x1.0p-24f;
4859 float y = 1.5f + x;
4960 return (y == 1.5f - x);
61#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
5062}
5163
5264// Quick free-standing test whether fegetround() == FE_TOWARDZERO.
......@@ -60,13 +72,20 @@ LIBC_INLINE bool fenv_is_round_to_nearest() {
6072// = 2^-22 for FE_TONEAREST, FE_UPWARD
6173// = 0 for FE_DOWNWARD
6274LIBC_INLINE bool fenv_is_round_to_zero() {
75#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
76 return false;
77#else
6378 static volatile float x = 0x1.0p-24f;
6479 float y = x;
6580 return ((0x1.000002p0f + y) + (-1.0f - y) == 0x1.0p-23f);
81#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
6682}
6783
6884// Quick free standing get rounding mode based on the above observations.
6985LIBC_INLINE int quick_get_round() {
86#ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
87 return FE_TONEAREST;
88#else
7089 static volatile float x = 0x1.0p-24f;
7190 float y = x;
7291 float z = (0x1.000002p0f + y) + (-1.0f - y);
......@@ -76,11 +95,12 @@ LIBC_INLINE int quick_get_round() {
7695 if (z == 0x1.0p-23f)
7796 return FE_TOWARDZERO;
7897 return (2.0f + y == 2.0f) ? FE_TONEAREST : FE_UPWARD;
98#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
7999}
80100
81101} // namespace generic
82102
83LIBC_INLINE static constexpr bool fenv_is_round_up() {
103LIBC_INLINE LIBC_CONSTEXPR_DEFAULT bool fenv_is_round_up() {
84104 if (cpp::is_constant_evaluated()) {
85105 return false;
86106 } else {
......@@ -88,7 +108,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_up() {
88108 }
89109}
90110
91LIBC_INLINE static constexpr bool fenv_is_round_down() {
111LIBC_INLINE LIBC_CONSTEXPR_DEFAULT bool fenv_is_round_down() {
92112 if (cpp::is_constant_evaluated()) {
93113 return false;
94114 } else {
......@@ -96,7 +116,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_down() {
96116 }
97117}
98118
99LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
119LIBC_INLINE LIBC_CONSTEXPR_DEFAULT bool fenv_is_round_to_nearest() {
100120 if (cpp::is_constant_evaluated()) {
101121 return true;
102122 } else {
......@@ -104,7 +124,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_to_nearest() {
104124 }
105125}
106126
107LIBC_INLINE static constexpr bool fenv_is_round_to_zero() {
127LIBC_INLINE LIBC_CONSTEXPR_DEFAULT bool fenv_is_round_to_zero() {
108128 if (cpp::is_constant_evaluated()) {
109129 return false;
110130 } else {
......@@ -113,7 +133,7 @@ LIBC_INLINE static constexpr bool fenv_is_round_to_zero() {
113133}
114134
115135// Quick free standing get rounding mode based on the above observations.
116LIBC_INLINE static constexpr int quick_get_round() {
136LIBC_INLINE LIBC_CONSTEXPR_DEFAULT int quick_get_round() {
117137 if (cpp::is_constant_evaluated()) {
118138 return FE_TONEAREST;
119139 } else {
lib/libcxx/libc/src/__support/big_int.h+35-49
......@@ -242,10 +242,9 @@ LIBC_INLINE constexpr void quick_mul_hi(cpp::array<word, N> &dst,
242242
243243template <typename word, size_t N>
244244LIBC_INLINE constexpr bool is_negative(const cpp::array<word, N> &array) {
245 using signed_word = cpp::make_signed_t<word>;
246 return cpp::bit_cast<signed_word>(array.back()) < 0;
245 constexpr size_t WORD_BITS = cpp::numeric_limits<word>::digits;
246 return (array.back() >> (WORD_BITS - 1)) != 0;
247247}
248
249248// An enum for the shift function below.
250249enum Direction { LEFT, RIGHT };
251250
......@@ -257,9 +256,11 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,
257256 size_t offset) {
258257 static_assert(direction == LEFT || direction == RIGHT);
259258 constexpr size_t WORD_BITS = cpp::numeric_limits<word>::digits;
259#if LIBC_HAS_BUILTIN_BIT_CAST
260260#ifdef LIBC_TYPES_HAS_INT128
261261 constexpr size_t TOTAL_BITS = N * WORD_BITS;
262 if constexpr (TOTAL_BITS == 128) {
262 if constexpr (TOTAL_BITS == 128 &&
263 __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) {
263264 using type = cpp::conditional_t<is_signed, __int128_t, __uint128_t>;
264265 auto tmp = cpp::bit_cast<type>(array);
265266 if constexpr (direction == LEFT)
......@@ -269,6 +270,8 @@ LIBC_INLINE constexpr cpp::array<word, N> shift(cpp::array<word, N> array,
269270 return cpp::bit_cast<cpp::array<word, N>>(tmp);
270271 }
271272#endif
273#endif // LIBC_HAS_BUILTIN_BIT_CAST
274
272275 if (LIBC_UNLIKELY(offset == 0))
273276 return array;
274277 const bool is_neg = is_signed && is_negative(array);
......@@ -336,8 +339,8 @@ private:
336339 "WordType must be unsigned integer.");
337340
338341 struct Division {
339 BigInt quotient;
340 BigInt remainder;
342 BigInt quotient{};
343 BigInt remainder{};
341344 };
342345
343346public:
......@@ -355,7 +358,7 @@ public:
355358
356359 LIBC_INLINE_VAR static constexpr size_t WORD_COUNT = Bits / WORD_SIZE;
357360
358 cpp::array<WordType, WORD_COUNT> val{}; // zero initialized.
361 cpp::array<WordType, WORD_COUNT> val;
359362
360363 LIBC_INLINE constexpr BigInt() = default;
361364
......@@ -363,9 +366,10 @@ public:
363366
364367 template <size_t OtherBits, bool OtherSigned, typename OtherWordType>
365368 LIBC_INLINE constexpr BigInt(
366 const BigInt<OtherBits, OtherSigned, OtherWordType> &other) {
369 const BigInt<OtherBits, OtherSigned, OtherWordType> &other)
370 : val{} {
367371 using BigIntOther = BigInt<OtherBits, OtherSigned, OtherWordType>;
368 const bool should_sign_extend = Signed && other.is_neg();
372 [[maybe_unused]] const bool should_sign_extend = Signed && other.is_neg();
369373
370374 static_assert(!(Bits == OtherBits && WORD_SIZE != BigIntOther::WORD_SIZE) &&
371375 "This is currently untested for casting between bigints with "
......@@ -453,20 +457,22 @@ public:
453457 }
454458
455459 // Construct a BigInt from a C array.
456 template <size_t N> LIBC_INLINE constexpr BigInt(const WordType (&nums)[N]) {
460 template <size_t N>
461 LIBC_INLINE constexpr BigInt(const WordType (&nums)[N]) : val{} {
457462 static_assert(N == WORD_COUNT);
458463 for (size_t i = 0; i < WORD_COUNT; ++i)
459464 val[i] = nums[i];
460465 }
461466
462467 LIBC_INLINE constexpr explicit BigInt(
463 const cpp::array<WordType, WORD_COUNT> &words) {
468 const cpp::array<WordType, WORD_COUNT> &words)
469 : val{} {
464470 val = words;
465471 }
466472
467473 // Initialize the first word to |v| and the rest to 0.
468474 template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T>>>
469 LIBC_INLINE constexpr BigInt(T v) {
475 LIBC_INLINE constexpr BigInt(T v) : val{} {
470476 constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT;
471477 const bool is_neg = v < 0;
472478 for (size_t i = 0; i < WORD_COUNT; ++i) {
......@@ -488,7 +494,7 @@ public:
488494 LIBC_INLINE static constexpr BigInt one() { return BigInt(1); }
489495 LIBC_INLINE static constexpr BigInt all_ones() { return ~zero(); }
490496 LIBC_INLINE static constexpr BigInt min() {
491 BigInt out;
497 BigInt out{};
492498 if constexpr (SIGNED)
493499 out.set_msb();
494500 return out;
......@@ -601,7 +607,7 @@ public:
601607 template <size_t OtherBits>
602608 LIBC_INLINE constexpr auto
603609 ful_mul(const BigInt<OtherBits, Signed, WordType> &other) const {
604 BigInt<Bits + OtherBits, Signed, WordType> result;
610 BigInt<Bits + OtherBits, Signed, WordType> result{};
605611 multiword::multiply_with_carry(result.val, val, other.val);
606612 return result;
607613 }
......@@ -633,7 +639,7 @@ public:
633639 // 256 4 16 10 3
634640 // 512 8 64 36 7
635641 LIBC_INLINE constexpr BigInt quick_mul_hi(const BigInt &other) const {
636 BigInt result;
642 BigInt result{};
637643 multiword::quick_mul_hi(result.val, val, other.val);
638644 return result;
639645 }
......@@ -686,7 +692,7 @@ public:
686692 // And finally we perform some extra alignment steps for the remaining bits.
687693 LIBC_INLINE constexpr cpp::optional<BigInt>
688694 div_uint_half_times_pow_2(multiword::half_width_t<WordType> x, size_t e) {
689 BigInt remainder;
695 BigInt remainder{};
690696 if (x == 0)
691697 return cpp::nullopt;
692698 if (e >= Bits) {
......@@ -694,7 +700,7 @@ public:
694700 *this = BigInt<Bits, false, WordType>();
695701 return remainder;
696702 }
697 BigInt quotient;
703 BigInt quotient{};
698704 WordType x_word = static_cast<WordType>(x);
699705 constexpr size_t LOG2_WORD_SIZE =
700706 static_cast<size_t>(cpp::bit_width(WORD_SIZE) - 1);
......@@ -846,13 +852,13 @@ public:
846852#define DEFINE_BINOP(OP) \
847853 LIBC_INLINE friend constexpr BigInt operator OP(const BigInt &lhs, \
848854 const BigInt &rhs) { \
849 BigInt result; \
855 BigInt result{}; \
850856 for (size_t i = 0; i < WORD_COUNT; ++i) \
851857 result[i] = lhs[i] OP rhs[i]; \
852858 return result; \
853859 } \
854 LIBC_INLINE friend constexpr BigInt operator OP##=(BigInt &lhs, \
855 const BigInt &rhs) { \
860 LIBC_INLINE friend constexpr BigInt operator OP## = \
861 (BigInt & lhs, const BigInt &rhs) { \
856862 for (size_t i = 0; i < WORD_COUNT; ++i) \
857863 lhs[i] OP## = rhs[i]; \
858864 return lhs; \
......@@ -864,7 +870,7 @@ public:
864870#undef DEFINE_BINOP
865871
866872 LIBC_INLINE constexpr BigInt operator~() const {
867 BigInt result;
873 BigInt result{};
868874 for (size_t i = 0; i < WORD_COUNT; ++i)
869875 result[i] = static_cast<WordType>(~val[i]);
870876 return result;
......@@ -1004,7 +1010,7 @@ private:
10041010 LIBC_INLINE constexpr static Division divide_unsigned(const BigInt &dividend,
10051011 const BigInt &divider) {
10061012 BigInt remainder = dividend;
1007 BigInt quotient;
1013 BigInt quotient{};
10081014 if (remainder >= divider) {
10091015 BigInt subtractor = divider;
10101016 int cur_bit = multiword::countl_zero(subtractor.val) -
......@@ -1181,31 +1187,6 @@ LIBC_INLINE_VAR constexpr bool is_unsigned_integral_or_big_int_v =
11811187
11821188namespace cpp {
11831189
1184// Specialization of cpp::bit_cast ('bit.h') from T to BigInt.
1185template <typename To, typename From>
1186LIBC_INLINE constexpr cpp::enable_if_t<
1187 (sizeof(To) == sizeof(From)) && cpp::is_trivially_copyable<To>::value &&
1188 cpp::is_trivially_copyable<From>::value && is_big_int<To>::value,
1189 To>
1190bit_cast(const From &from) {
1191 To out;
1192 using Storage = decltype(out.val);
1193 out.val = cpp::bit_cast<Storage>(from);
1194 return out;
1195}
1196
1197// Specialization of cpp::bit_cast ('bit.h') from BigInt to T.
1198template <typename To, size_t Bits>
1199LIBC_INLINE constexpr cpp::enable_if_t<
1200 sizeof(To) == sizeof(UInt<Bits>) &&
1201 cpp::is_trivially_constructible<To>::value &&
1202 cpp::is_trivially_copyable<To>::value &&
1203 cpp::is_trivially_copyable<UInt<Bits>>::value,
1204 To>
1205bit_cast(const UInt<Bits> &from) {
1206 return cpp::bit_cast<To>(from.val);
1207}
1208
12091190// Specialization of cpp::popcount ('bit.h') for BigInt.
12101191template <typename T>
12111192[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int>
......@@ -1311,7 +1292,7 @@ mask_trailing_ones() {
13111292 return T::all_ones();
13121293 constexpr size_t QUOTIENT = count / T::WORD_SIZE;
13131294 constexpr size_t REMAINDER = count % T::WORD_SIZE;
1314 T out; // zero initialized
1295 T out{};
13151296 for (size_t i = 0; i <= QUOTIENT; ++i)
13161297 out[i] = i < QUOTIENT
13171298 ? cpp::numeric_limits<typename T::word_type>::max()
......@@ -1327,7 +1308,7 @@ LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T> mask_leading_ones() {
13271308 return T::all_ones();
13281309 constexpr size_t QUOTIENT = (T::BITS - count - 1U) / T::WORD_SIZE;
13291310 constexpr size_t REMAINDER = count % T::WORD_SIZE;
1330 T out; // zero initialized
1311 T out{};
13311312 for (size_t i = QUOTIENT; i < T::WORD_COUNT; ++i)
13321313 out[i] = i > QUOTIENT
13331314 ? cpp::numeric_limits<typename T::word_type>::max()
......@@ -1386,6 +1367,11 @@ first_trailing_one(T value) {
13861367 return value == 0 ? 0 : cpp::countr_zero(value) + 1;
13871368}
13881369
1370static_assert(LIBC_NAMESPACE::cpp::is_trivially_constructible<
1371 LIBC_NAMESPACE::BigInt<128, false>>::value);
1372static_assert(LIBC_NAMESPACE::cpp::is_trivially_copyable<
1373 LIBC_NAMESPACE::BigInt<128, false>>::value);
1374
13891375} // namespace LIBC_NAMESPACE_DECL
13901376
13911377#endif // LLVM_LIBC_SRC___SUPPORT_BIG_INT_H
lib/libcxx/libc/src/__support/common.h+45-32
......@@ -22,6 +22,10 @@
2222#define LLVM_LIBC_FUNCTION_ATTR
2323#endif
2424
25#ifndef LLVM_LIBC_VARIABLE_ATTR
26#define LLVM_LIBC_VARIABLE_ATTR
27#endif
28
2529// clang-format off
2630// Allow each function `func` to have extra attributes specified by defining:
2731// `LLVM_LIBC_FUNCTION_ATTR_func` macro, which should always start with
......@@ -33,7 +37,9 @@
3337// clang-format on
3438#define LLVM_LIBC_EMPTY
3539
40#define GET_NOTHING(...) 0
3641#define GET_SECOND(first, second, ...) second
42#define GET_FIFTH(first, second, third, fourth, fifth, ...) fifth
3743#define EXPAND_THEN_SECOND(name) GET_SECOND(name, LLVM_LIBC_EMPTY)
3844
3945#define LLVM_LIBC_ATTR(name) EXPAND_THEN_SECOND(LLVM_LIBC_FUNCTION_ATTR_##name)
......@@ -44,50 +50,57 @@
4450// symbol. Moreover, a C symbol `func` in macOS is mangled as `_func`.
4551#if defined(LIBC_COPT_PUBLIC_PACKAGING) && !defined(LIBC_COMPILER_IS_MSVC)
4652#ifndef __APPLE__
47#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \
53#define LLVM_LIBC_FUNCTION_IMPL_4(type, name, arglist, c_alias) \
4854 LLVM_LIBC_ATTR(name) \
4955 LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \
50 __##name##_impl__ asm(#name); \
51 decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \
56 __##name##_impl__ asm(c_alias); \
57 decltype(LIBC_NAMESPACE::name) name [[gnu::alias(c_alias)]]; \
5258 type __##name##_impl__ arglist
5359#else // __APPLE__
54#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \
60#define LLVM_LIBC_FUNCTION_IMPL_4(type, name, arglist, c_alias) \
5561 LLVM_LIBC_ATTR(name) \
56 LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) name asm("_" #name); \
62 LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) name asm( \
63 "_" c_alias); \
5764 type name arglist
5865#endif // __APPLE__
66
5967#else // LIBC_COPT_PUBLIC_PACKAGING
60#define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) type name arglist
68#define LLVM_LIBC_FUNCTION_IMPL_4(type, name, arglist, c_alias) \
69 type name arglist
6170#endif // LIBC_COPT_PUBLIC_PACKAGING
6271
63// This extra layer of macro allows `name` to be a macro to rename a function.
64#define LLVM_LIBC_FUNCTION(type, name, arglist) \
65 LLVM_LIBC_FUNCTION_IMPL(type, name, arglist)
72#define LLVM_LIBC_FUNCTION_IMPL_3(type, name, arglist) \
73 LLVM_LIBC_FUNCTION_IMPL_4(type, name, arglist, #name)
6674
67namespace LIBC_NAMESPACE_DECL {
68namespace internal {
69LIBC_INLINE constexpr bool same_string(char const *lhs, char const *rhs) {
70 for (; *lhs || *rhs; ++lhs, ++rhs)
71 if (*lhs != *rhs)
72 return false;
73 return true;
74}
75} // namespace internal
76} // namespace LIBC_NAMESPACE_DECL
75// LLVM_LIBC_FUNCTION(type, name, arglist) is equivalent to
76// LLVM_LIBC_FUNCTION(type, name, arglist, #name)
77#define LLVM_LIBC_FUNCTION(...) \
78 GET_FIFTH(__VA_ARGS__, LLVM_LIBC_FUNCTION_IMPL_4, LLVM_LIBC_FUNCTION_IMPL_3, \
79 GET_NOTHING)(__VA_ARGS__)
7780
78#define __LIBC_MACRO_TO_STRING(str) #str
79#define LIBC_MACRO_TO_STRING(str) __LIBC_MACRO_TO_STRING(str)
81// At the moment, [[gnu::alias()]] is not supported on MacOS, and it is needed
82// to cleanly export and alias the C++ symbol `LIBC_NAMESPACE::func` with the C
83// symbol `func`. So for public packaging on MacOS, we will only export the C
84// symbol. Moreover, a C symbol `func` in macOS is mangled as `_func`.
85#if defined(LIBC_COPT_PUBLIC_PACKAGING) && !defined(LIBC_COMPILER_IS_MSVC)
86#ifndef __APPLE__
87#define LLVM_LIBC_VARIABLE_IMPL(type, name) \
88 LLVM_LIBC_ATTR(name) \
89 extern LLVM_LIBC_VARIABLE_ATTR decltype(LIBC_NAMESPACE::name) \
90 __##name##_impl__ asm(#name); \
91 extern decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \
92 type __##name##_impl__
93#else // __APPLE__
94#define LLVM_LIBC_VARIABLE_IMPL(type, name) \
95 LLVM_LIBC_ATTR(name) \
96 extern LLVM_LIBC_VARIABLE_ATTR decltype(LIBC_NAMESPACE::name) name asm( \
97 "_" #name); \
98 type name
99#endif // __APPLE__
100#else // LIBC_COPT_PUBLIC_PACKAGING
101#define LLVM_LIBC_VARIABLE_IMPL(type, name) type name
102#endif // LIBC_COPT_PUBLIC_PACKAGING
80103
81// LLVM_LIBC_IS_DEFINED checks whether a particular macro is defined.
82// Usage: constexpr bool kUseAvx = LLVM_LIBC_IS_DEFINED(__AVX__);
83//
84// This works by comparing the stringified version of the macro with and without
85// evaluation. If FOO is not undefined both stringifications yield "FOO". If FOO
86// is defined, one stringification yields "FOO" while the other yields its
87// stringified value "1".
88#define LLVM_LIBC_IS_DEFINED(macro) \
89 !LIBC_NAMESPACE::internal::same_string( \
90 LLVM_LIBC_IS_DEFINED__EVAL_AND_STRINGIZE(macro), #macro)
91#define LLVM_LIBC_IS_DEFINED__EVAL_AND_STRINGIZE(s) #s
104#define LLVM_LIBC_VARIABLE(type, name) LLVM_LIBC_VARIABLE_IMPL(type, name)
92105
93106#endif // LLVM_LIBC_SRC___SUPPORT_COMMON_H
lib/libcxx/libc/src/__support/ctype_utils.h+27-15
......@@ -37,7 +37,7 @@ namespace internal {
3737// EBCDIC. Technically we could use some smaller ranges, but that's even harder
3838// to read.
3939
40LIBC_INLINE static constexpr bool islower(char ch) {
40LIBC_INLINE constexpr bool islower(char ch) {
4141 switch (ch) {
4242 case 'a':
4343 case 'b':
......@@ -71,7 +71,7 @@ LIBC_INLINE static constexpr bool islower(char ch) {
7171 }
7272}
7373
74LIBC_INLINE static constexpr bool isupper(char ch) {
74LIBC_INLINE constexpr bool isupper(char ch) {
7575 switch (ch) {
7676 case 'A':
7777 case 'B':
......@@ -105,7 +105,7 @@ LIBC_INLINE static constexpr bool isupper(char ch) {
105105 }
106106}
107107
108LIBC_INLINE static constexpr bool isdigit(char ch) {
108LIBC_INLINE constexpr bool isdigit(char ch) {
109109 switch (ch) {
110110 case '0':
111111 case '1':
......@@ -123,7 +123,7 @@ LIBC_INLINE static constexpr bool isdigit(char ch) {
123123 }
124124}
125125
126LIBC_INLINE static constexpr char tolower(char ch) {
126LIBC_INLINE constexpr char tolower(char ch) {
127127 switch (ch) {
128128 case 'A':
129129 return 'a';
......@@ -182,7 +182,7 @@ LIBC_INLINE static constexpr char tolower(char ch) {
182182 }
183183}
184184
185LIBC_INLINE static constexpr char toupper(char ch) {
185LIBC_INLINE constexpr char toupper(char ch) {
186186 switch (ch) {
187187 case 'a':
188188 return 'A';
......@@ -241,7 +241,7 @@ LIBC_INLINE static constexpr char toupper(char ch) {
241241 }
242242}
243243
244LIBC_INLINE static constexpr bool isalpha(char ch) {
244LIBC_INLINE constexpr bool isalpha(char ch) {
245245 switch (ch) {
246246 case 'a':
247247 case 'b':
......@@ -301,7 +301,7 @@ LIBC_INLINE static constexpr bool isalpha(char ch) {
301301 }
302302}
303303
304LIBC_INLINE static constexpr bool isalnum(char ch) {
304LIBC_INLINE constexpr bool isalnum(char ch) {
305305 switch (ch) {
306306 case 'a':
307307 case 'b':
......@@ -371,7 +371,8 @@ LIBC_INLINE static constexpr bool isalnum(char ch) {
371371 }
372372}
373373
374LIBC_INLINE static constexpr int b36_char_to_int(char ch) {
374#ifndef LIBC_COPT_CTYPE_SMALLER_ASCII
375LIBC_INLINE constexpr int b36_char_to_int(char ch) {
375376 switch (ch) {
376377 case '0':
377378 return 0;
......@@ -475,8 +476,21 @@ LIBC_INLINE static constexpr int b36_char_to_int(char ch) {
475476 return 0;
476477 }
477478}
479#else // LIBC_COPT_SMALL_ASCII_CTYPE
480// This version assumes ASCII for the tolower, but generates smaller code since
481// the switch version of this function ends up with a table. This should only be
482// used when the target is known to be ASCII.
483LIBC_INLINE constexpr int b36_char_to_int(char ch) {
484 if (ch >= '0' && ch <= '9')
485 return ch - '0';
486 char ch_unsafe_lower = ch | 32;
487 if (ch_unsafe_lower >= 'a' && ch_unsafe_lower <= 'z')
488 return ch_unsafe_lower - 'a' + 10;
489 return 0;
490}
491#endif // LIBC_COPT_SMALL_ASCII_CTYPE
478492
479LIBC_INLINE static constexpr char int_to_b36_char(int num) {
493LIBC_INLINE constexpr char int_to_b36_char(int num) {
480494 // Can't actually use LIBC_ASSERT here because it depends on integer_to_string
481495 // which depends on this.
482496
......@@ -559,7 +573,7 @@ LIBC_INLINE static constexpr char int_to_b36_char(int num) {
559573 }
560574}
561575
562LIBC_INLINE static constexpr bool isspace(char ch) {
576LIBC_INLINE constexpr bool isspace(char ch) {
563577 switch (ch) {
564578 case ' ':
565579 case '\t':
......@@ -574,14 +588,12 @@ LIBC_INLINE static constexpr bool isspace(char ch) {
574588}
575589
576590// not yet encoding independent.
577LIBC_INLINE static constexpr bool isgraph(char ch) {
578 return 0x20 < ch && ch < 0x7f;
579}
591LIBC_INLINE constexpr bool isgraph(char ch) { return 0x20 < ch && ch < 0x7f; }
580592
581593// An overload which provides a way to compare input with specific character
582594// values, when input can be of a regular or a wide character type.
583LIBC_INLINE static constexpr bool is_char_or_wchar(char ch, char c_value,
584 [[maybe_unused]] wchar_t) {
595LIBC_INLINE constexpr bool is_char_or_wchar(char ch, char c_value,
596 [[maybe_unused]] wchar_t) {
585597 return (ch == c_value);
586598}
587599
lib/libcxx/libc/src/__support/high_precision_decimal.h+1-1
......@@ -1,7 +1,7 @@
11//===-- High Precision Decimal ----------------------------------*- C++ -*-===//
22//
33// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See httpss//llvm.org/LICENSE.txt for license information.
4// See https://llvm.org/LICENSE.txt for license information.
55// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66//
77//===----------------------------------------------------------------------===//
lib/libcxx/libc/src/__support/libc_assert.h+4-11
......@@ -25,8 +25,9 @@
2525#include "src/__support/OSUtil/exit.h"
2626#include "src/__support/OSUtil/io.h"
2727#include "src/__support/integer_to_string.h"
28#include "src/__support/macros/attributes.h" // For LIBC_INLINE
28#include "src/__support/macros/attributes.h" // For LIBC_INLINE
2929#include "src/__support/macros/config.h"
30#include "src/__support/macros/macro-utils.h"
3031#include "src/__support/macros/optimization.h" // For LIBC_UNLIKELY
3132
3233namespace LIBC_NAMESPACE_DECL {
......@@ -65,19 +66,11 @@ LIBC_INLINE void report_assertion_failure(const char *assertion,
6566 } while (false)
6667#else
6768
68// Convert __LINE__ to a string using macros. The indirection is necessary
69// because otherwise it will turn "__LINE__" into a string, not its value. The
70// value is evaluated in the indirection step.
71#define __LIBC_MACRO_TO_STR(x) #x
72#define __LIBC_MACRO_TO_STR_INDIR(y) __LIBC_MACRO_TO_STR(y)
73#define __LIBC_LINE_STR__ __LIBC_MACRO_TO_STR_INDIR(__LINE__)
74
7569#define LIBC_ASSERT(COND) \
7670 do { \
7771 if (LIBC_UNLIKELY(!(COND))) { \
78 LIBC_NAMESPACE::write_to_stderr(__FILE__ ":" __LIBC_LINE_STR__ \
79 ": Assertion failed: '" #COND \
80 "' in function: '"); \
72 LIBC_NAMESPACE::write_to_stderr(__FILE__ ":" LLVM_LIBC_STRINGIFY( \
73 __LINE__) ": Assertion failed: '" #COND "' in function: '"); \
8174 LIBC_NAMESPACE::write_to_stderr(__PRETTY_FUNCTION__); \
8275 LIBC_NAMESPACE::write_to_stderr("'\n"); \
8376 LIBC_NAMESPACE::internal::exit(0xFF); \
lib/libcxx/libc/src/__support/macros/attributes.h+74
......@@ -29,6 +29,80 @@
2929#define LIBC_INLINE_ASM __asm__ __volatile__
3030#define LIBC_UNUSED __attribute__((unused))
3131
32#ifndef LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED
33#if (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 900)) || \
34 (defined(LIBC_COMPILER_IS_CLANG) && LIBC_COMPILER_CLANG_VER >= 900)
35#define LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED 1
36#else
37#define LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED \
38 (__has_builtin(__builtin_is_constant_evaluated))
39#endif // (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 900)) ||
40 // (defined(LIBC_COMPILER_IS_CLANG) && LIBC_COMPILER_CLANG
41#endif // LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED
42
43#ifndef LIBC_HAS_BUILTIN_BIT_CAST
44#if __has_builtin(__builtin_bit_cast) || defined(LIBC_COMPILER_IS_MSVC)
45#define LIBC_HAS_BUILTIN_BIT_CAST 1
46#else
47#define LIBC_HAS_BUILTIN_BIT_CAST 0
48#endif // has_builtin(__builtin_bit_cast)
49#endif // LIBC_HAS_BUILTIN_BIT_CAST
50
51#if LIBC_HAS_BUILTIN_BIT_CAST
52#define LIBC_BIT_CAST_CONSTEXPR constexpr
53#define LIBC_BIT_CAST_CONSTEXPR_VAR constexpr
54#else
55#define LIBC_BIT_CAST_CONSTEXPR
56#define LIBC_BIT_CAST_CONSTEXPR_VAR const
57#endif // LIBC_HAS_BUILTIN_BIT_CAST
58
59#ifndef LIBC_HAS_CONSTANT_EVALUATION
60#define LIBC_HAS_CONSTANT_EVALUATION \
61 (LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED && LIBC_HAS_BUILTIN_BIT_CAST)
62#endif // LIBC_HAS_CONSTANT_EVALUATION
63
64#if LIBC_HAS_CONSTANT_EVALUATION
65#define LIBC_CONSTEXPR_DEFAULT constexpr
66#define LIBC_CONSTEXPR_VAR_DEFAULT constexpr
67#else
68#define LIBC_CONSTEXPR_DEFAULT
69#define LIBC_CONSTEXPR_VAR_DEFAULT const
70#endif // LIBC_HAS_CONSTANT_EVALUATION
71
72// TODO: Remove the macro once Clang/LLVM bump their minimum compilers' version.
73// The reason for indirection is GCC is known to fail with constexpr qualified
74// functions that doesn't produce constant expression.
75// Also, there are some circular dependency in the generic functions without
76// __builtin_func for the following functions:
77// fputil::fma
78// fputil::sqrt
79#if LIBC_ENABLE_CONSTEXPR && LIBC_HAS_CONSTANT_EVALUATION
80#define LIBC_USE_CONSTEXPR
81#define LIBC_CONSTEXPR constexpr
82#define LIBC_CONSTEXPR_VAR constexpr
83#else
84#define LIBC_CONSTEXPR
85#define LIBC_CONSTEXPR_VAR const
86#endif // LIBC_USE_CONSTEXPR
87
88#ifndef LIBC_HAS_BUILTIN_IS_ASSIGNABLE
89#if (__has_builtin(__is_assignable) || \
90 (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 800)))
91#define LIBC_HAS_BUILTIN_IS_ASSIGNABLE 1
92#else
93#define LIBC_HAS_BUILTIN_IS_ASSIGNABLE 0
94#endif
95#endif // LIBC_HAS_BUILTIN_IS_ASSIGNABLE
96
97#ifndef LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE
98#if (__has_builtin(__is_constructible) || \
99 (defined(LIBC_COMPILER_IS_GCC) && (LIBC_COMPILER_GCC_VER >= 800)))
100#define LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1
101#else
102#define LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE 0
103#endif
104#endif // LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE
105
32106// Uses the platform specific specialization
33107#define LIBC_THREAD_MODE_PLATFORM 0
34108
lib/libcxx/libc/src/__support/macros/config.h+14
......@@ -48,6 +48,10 @@
4848
4949#define __builtin_prefetch(X, Y, Z)
5050
51#define LIBC_HAS_BUILTIN_IS_CONSTANT_EVALUATED 1
52#define LIBC_HAS_BUILTIN_IS_ASSIGNABLE 1
53#define LIBC_HAS_BUILTIN_IS_CONSTRUCTIBLE 1
54
5155#endif // LIBC_COMPILER_IS_MSVC
5256
5357#ifdef __clang__
......@@ -66,4 +70,14 @@
6670#define LIBC_NAMESPACE_DECL LIBC_NAMESPACE
6771#endif
6872
73// IMPORTANT (USE WITH CAUTION): This macro is intended to be used at the top of
74// the file and set to 1. It alters the signatures of some functions to have
75// constexpr qualifier and forces the use of constexpr-compatible
76// implementation, which might be a completely different code path or
77// instructions. Some of these functions exploit platform-specific non-constexpr
78// implementations to achieve certain goals, thus it is disabled by default.
79#ifndef LIBC_ENABLE_CONSTEXPR
80#define LIBC_ENABLE_CONSTEXPR 0
81#endif
82
6983#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H
lib/libcxx/libc/src/__support/macros/macro-utils.h created+16
......@@ -0,0 +1,16 @@
1//===-- Macros used by other macros ----------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_MACRO_UTILS_H
10#define LLVM_LIBC_SRC___SUPPORT_MACROS_MACRO_UTILS_H
11
12// Stringify the argument after an extra pass of macro expansion.
13#define LLVM_LIBC_STRINGIFY(x) LLVM_LIBC_STRINGIFY_IMPL(x)
14#define LLVM_LIBC_STRINGIFY_IMPL(x) #x
15
16#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_MACRO_UTILS_H
lib/libcxx/libc/src/__support/macros/optimization.h+18-7
......@@ -32,8 +32,13 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
3232#define LIBC_LOOP_NOUNROLL _Pragma("nounroll")
3333#define LIBC_LOOP_UNROLL _Pragma("unroll")
3434#elif defined(LIBC_COMPILER_IS_GCC)
35#if LIBC_COMPILER_GCC_VER >= 800
3536#define LIBC_LOOP_NOUNROLL _Pragma("GCC unroll 0")
3637#define LIBC_LOOP_UNROLL _Pragma("GCC unroll 2048")
38#else
39#define LIBC_LOOP_NOUNROLL
40#define LIBC_LOOP_UNROLL
41#endif
3742#elif defined(LIBC_COMPILER_IS_MSVC)
3843#define LIBC_LOOP_NOUNROLL
3944#define LIBC_LOOP_UNROLL
......@@ -47,33 +52,39 @@ LIBC_INLINE constexpr bool expects_bool_condition(T value, T expected) {
4752#define LIBC_MATH_SMALL_TABLES 0x02
4853#define LIBC_MATH_NO_ERRNO 0x04
4954#define LIBC_MATH_NO_EXCEPT 0x08
55#define LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT 0x10
56#define LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY 0x20
5057#define LIBC_MATH_FAST \
5158 (LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES | \
52 LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT)
53#define LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT 0x10
59 LIBC_MATH_NO_ERRNO | LIBC_MATH_NO_EXCEPT | \
60 LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY)
5461
5562#ifndef LIBC_MATH
5663#define LIBC_MATH 0
5764#endif // LIBC_MATH
5865
59#if (LIBC_MATH & LIBC_MATH_SKIP_ACCURATE_PASS)
66#if ((LIBC_MATH) & LIBC_MATH_SKIP_ACCURATE_PASS)
6067#define LIBC_MATH_HAS_SKIP_ACCURATE_PASS
6168#endif
6269
63#if (LIBC_MATH & LIBC_MATH_SMALL_TABLES)
70#if ((LIBC_MATH) & LIBC_MATH_SMALL_TABLES)
6471#define LIBC_MATH_HAS_SMALL_TABLES
6572#endif
6673
67#if (LIBC_MATH & LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT)
74#if ((LIBC_MATH) & LIBC_MATH_INTERMEDIATE_COMP_IN_FLOAT)
6875#define LIBC_MATH_HAS_INTERMEDIATE_COMP_IN_FLOAT
6976#endif
7077
71#if (LIBC_MATH & LIBC_MATH_NO_ERRNO)
78#if ((LIBC_MATH) & LIBC_MATH_NO_ERRNO)
7279#define LIBC_MATH_HAS_NO_ERRNO
7380#endif
7481
75#if (LIBC_MATH & LIBC_MATH_NO_EXCEPT)
82#if ((LIBC_MATH) & LIBC_MATH_NO_EXCEPT)
7683#define LIBC_MATH_HAS_NO_EXCEPT
7784#endif
7885
86#if ((LIBC_MATH) & LIBC_MATH_ASSUME_ROUND_NEAREST_ONLY)
87#define LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
88#endif
89
7990#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H
lib/libcxx/libc/src/__support/macros/properties/architectures.h+6-1
......@@ -13,11 +13,16 @@
1313#define LIBC_TARGET_ARCH_IS_AMDGPU
1414#endif
1515
16#if defined(__SPIRV__)
17#define LIBC_TARGET_ARCH_IS_SPIRV
18#endif
19
1620#if defined(__NVPTX__)
1721#define LIBC_TARGET_ARCH_IS_NVPTX
1822#endif
1923
20#if defined(LIBC_TARGET_ARCH_IS_NVPTX) || defined(LIBC_TARGET_ARCH_IS_AMDGPU)
24#if defined(LIBC_TARGET_ARCH_IS_NVPTX) || \
25 defined(LIBC_TARGET_ARCH_IS_AMDGPU) || defined(LIBC_TARGET_ARCH_IS_SPIRV)
2126#define LIBC_TARGET_ARCH_IS_GPU
2227#endif
2328
lib/libcxx/libc/src/__support/macros/properties/cpu_features.h+7-2
......@@ -56,6 +56,10 @@
5656#define LIBC_TARGET_CPU_HAS_AVX512BW
5757#endif
5858
59#if defined(__AVX512F__) || defined(__AVX2__)
60#define LIBC_TARGET_CPU_HAS_GATHER
61#endif
62
5963#if defined(__ARM_FP)
6064#if (__ARM_FP & 0x2)
6165#define LIBC_TARGET_CPU_HAS_ARM_FPU_HALF
......@@ -91,13 +95,14 @@
9195#endif // LIBC_TARGET_CPU_HAS_RISCV_FPU_DOUBLE
9296#endif // __riscv_flen
9397
94#if defined(__NVPTX__) || defined(__AMDGPU__)
98#if defined(__NVPTX__) || defined(__AMDGPU__) || defined(__SPIRV__)
9599#define LIBC_TARGET_CPU_HAS_FPU_FLOAT
96100#define LIBC_TARGET_CPU_HAS_FPU_DOUBLE
97101#endif
98102
99103#if defined(__ARM_FEATURE_FMA) || (defined(__AVX2__) && defined(__FMA__)) || \
100 defined(__NVPTX__) || defined(__AMDGPU__) || defined(__riscv_flen)
104 defined(__NVPTX__) || defined(__AMDGPU__) || defined(__riscv_flen) || \
105 defined(__SPIRV__)
101106#define LIBC_TARGET_CPU_HAS_FMA
102107// Provide a more fine-grained control of FMA instruction for ARM targets.
103108#if defined(LIBC_TARGET_CPU_HAS_FPU_HALF)
lib/libcxx/libc/src/__support/macros/sanitizer.h+7-6
......@@ -26,24 +26,25 @@
2626#ifdef LIBC_HAS_MEMORY_SANITIZER
2727// Only perform MSAN unpoison in non-constexpr context.
2828#include <sanitizer/msan_interface.h>
29#define MSAN_UNPOISON(addr, size) \
29#define LIBC_MSAN_UNPOISON(addr, size) \
3030 do { \
3131 if (!__builtin_is_constant_evaluated()) \
3232 __msan_unpoison(addr, size); \
3333 } while (0)
3434#else
35#define MSAN_UNPOISON(ptr, size)
35#define LIBC_MSAN_UNPOISON(ptr, size)
3636#endif
3737
3838#ifdef LIBC_HAS_ADDRESS_SANITIZER
3939#include <sanitizer/asan_interface.h>
40#define ASAN_POISON_MEMORY_REGION(addr, size) \
40#define LIBC_ASAN_POISON_MEMORY_REGION(addr, size) \
4141 __asan_poison_memory_region((addr), (size))
42#define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
42#define LIBC_ASAN_UNPOISON_MEMORY_REGION(addr, size) \
4343 __asan_unpoison_memory_region((addr), (size))
4444#else
45#define ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
46#define ASAN_UNPOISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
45#define LIBC_ASAN_POISON_MEMORY_REGION(addr, size) ((void)(addr), (void)(size))
46#define LIBC_ASAN_UNPOISON_MEMORY_REGION(addr, size) \
47 ((void)(addr), (void)(size))
4748#endif
4849
4950#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_SANITIZER_H
lib/libcxx/libc/src/__support/math_extras.h+15
......@@ -80,6 +80,21 @@ template <typename T>
8080#endif // __builtin_sub_overflow
8181}
8282
83template <typename T>
84[[nodiscard]] LIBC_INLINE constexpr bool mul_overflow(T a, T b, T &res) {
85#if __has_builtin(__builtin_mul_overflow)
86 return __builtin_mul_overflow(a, b, &res);
87#else
88 T max = cpp::numeric_limits<T>::max();
89 T min = cpp::numeric_limits<T>::min();
90 bool overflow = (b > 0 && (a > max / b || a < min / b)) ||
91 (b < 0 && (a < max / b || a > min / b));
92 if (!overflow)
93 res = a * b;
94 return overflow;
95#endif
96}
97
8398#define RETURN_IF(TYPE, BUILTIN) \
8499 if constexpr (cpp::is_same_v<T, TYPE>) \
85100 return BUILTIN(a, b, carry_in, &carry_out);
lib/libcxx/libc/src/__support/str_to_float.h+14-9
......@@ -124,7 +124,7 @@ eisel_lemire(ExpandedFloat<T> init_num,
124124 // Wider Approximation
125125 UInt128 final_approx;
126126 // The halfway constant is used to check if the bits that will be shifted away
127 // intially are all 1. For doubles this is 64 (bitstype size) - 52 (final
127 // initially are all 1. For doubles this is 64 (bitstype size) - 52 (final
128128 // mantissa size) - 3 (we shift away the last two bits separately for
129129 // accuracy, and the most significant bit is ignored.) = 9 bits. Similarly,
130130 // it's 6 bits for floats in this case.
......@@ -262,7 +262,7 @@ eisel_lemire<long double>(ExpandedFloat<long double> init_num,
262262 (final_approx_lower < approx_lower ? 1 : 0);
263263
264264 // The halfway constant is used to check if the bits that will be shifted away
265 // intially are all 1. For 80 bit floats this is 128 (bitstype size) - 64
265 // initially are all 1. For 80 bit floats this is 128 (bitstype size) - 64
266266 // (final mantissa size) - 3 (we shift away the last two bits separately for
267267 // accuracy, and the most significant bit is ignored.) = 61 bits. Similarly,
268268 // it's 12 bits for 128 bit floats in this case.
......@@ -680,17 +680,15 @@ template <> LIBC_INLINE constexpr int32_t get_lower_bound<double>() {
680680// accuracy.
681681template <typename T, typename CharType>
682682LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float(
683 ExpandedFloat<T> init_num, bool truncated, RoundDirection round,
684 const CharType *__restrict numStart,
683 ExpandedFloat<T> init_num, [[maybe_unused]] bool truncated,
684 RoundDirection round, const CharType *__restrict numStart,
685685 const size_t num_len = cpp::numeric_limits<size_t>::max()) {
686686 using FPBits = typename fputil::FPBits<T>;
687 using StorageType = typename FPBits::StorageType;
688687
689 StorageType mantissa = init_num.mantissa;
690688 int32_t exp10 = init_num.exponent;
691689
692690 FloatConvertReturn<T> output;
693 cpp::optional<ExpandedFloat<T>> opt_output;
691 [[maybe_unused]] cpp::optional<ExpandedFloat<T>> opt_output;
694692
695693 // If the exponent is too large and can't be represented in this size of
696694 // float, return inf. These bounds are relatively loose, but are mostly
......@@ -725,6 +723,8 @@ LIBC_INLINE FloatConvertReturn<T> decimal_exp_to_float(
725723
726724#ifndef LIBC_COPT_STRTOFLOAT_DISABLE_EISEL_LEMIRE
727725 // Try Eisel-Lemire
726 using StorageType = typename FPBits::StorageType;
727 StorageType mantissa = init_num.mantissa;
728728 opt_output = eisel_lemire<T>(init_num, round);
729729 if (opt_output.has_value()) {
730730 if (!truncated) {
......@@ -1093,7 +1093,7 @@ hexadecimal_string_to_float(const CharType *__restrict src,
10931093}
10941094
10951095template <typename T, typename CharType>
1096LIBC_INLINE typename fputil::FPBits<T>::StorageType
1096LIBC_INLINE constexpr typename fputil::FPBits<T>::StorageType
10971097nan_mantissa_from_ncharseq(const CharType *str, size_t len) {
10981098 using FPBits = typename fputil::FPBits<T>;
10991099 using StorageType = typename FPBits::StorageType;
......@@ -1129,7 +1129,9 @@ strtofloatingpoint(const CharType *__restrict src) {
11291129
11301130 size_t index = first_non_whitespace(src);
11311131 int sign = get_sign(src + index);
1132#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
11321133 bool is_positive = (sign >= 0);
1134#endif
11331135 index += (sign != 0);
11341136
11351137 if (sign < 0) {
......@@ -1146,6 +1148,7 @@ strtofloatingpoint(const CharType *__restrict src) {
11461148 }
11471149
11481150 RoundDirection round_direction = RoundDirection::Nearest;
1151#ifndef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
11491152 switch (fputil::quick_get_round()) {
11501153 case FE_TONEAREST:
11511154 round_direction = RoundDirection::Nearest;
......@@ -1160,6 +1163,7 @@ strtofloatingpoint(const CharType *__restrict src) {
11601163 round_direction = RoundDirection::Down;
11611164 break;
11621165 }
1166#endif // LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
11631167
11641168 StrToNumResult<ExpandedFloat<T>> parse_result({0, 0});
11651169 if (base == 16) {
......@@ -1221,7 +1225,8 @@ strtofloatingpoint(const CharType *__restrict src) {
12211225 return {result.get_val(), static_cast<ptrdiff_t>(index), error};
12221226}
12231227
1224template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) {
1228template <class T>
1229LIBC_INLINE constexpr StrToNumResult<T> strtonan(const char *arg) {
12251230 using FPBits = typename fputil::FPBits<T>;
12261231 using StorageType = typename FPBits::StorageType;
12271232
lib/libcxx/libc/src/__support/str_to_integer.h+21-2
......@@ -33,7 +33,7 @@ namespace internal {
3333// Returns the idx to the first character in src that is not a whitespace
3434// character (as determined by isspace())
3535template <typename CharType>
36LIBC_INLINE size_t
36LIBC_INLINE constexpr size_t
3737first_non_whitespace(const CharType *__restrict src,
3838 size_t src_len = cpp::numeric_limits<size_t>::max()) {
3939 size_t src_cur = 0;
......@@ -65,6 +65,18 @@ LIBC_INLINE static bool is_hex_start(const CharType *__restrict src,
6565 b36_char_to_int(src[2]) < 16;
6666}
6767
68// checks if the next 3 characters of the string pointer are the start of a
69// binary number. Does not advance the string pointer.
70template <typename CharType>
71LIBC_INLINE static bool is_binary_start(const CharType *__restrict src,
72 size_t src_len) {
73 if (src_len < 3)
74 return false;
75 return is_char_or_wchar(src[0], '0', L'0') &&
76 is_char_or_wchar(tolower(src[1]), 'b', L'b') && isalnum(src[2]) &&
77 b36_char_to_int(src[2]) < 2;
78}
79
6880// Takes the address of the string pointer and parses the base from the start of
6981// it.
7082template <typename CharType>
......@@ -75,6 +87,10 @@ LIBC_INLINE static int infer_base(const CharType *__restrict src,
7587 // with values 10 through 15 respectively." (C standard 6.4.4.1)
7688 if (is_hex_start(src, src_len))
7789 return 16;
90 // A binary number is defined as "the prefix 0b or 0B optionally followed
91 // by a sequence of letters and digits." (C standard 7.24.1.7)
92 if (is_binary_start(src, src_len))
93 return 2;
7894 // An octal number is defined as "the prefix 0 optionally followed by a
7995 // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any
8096 // number that starts with 0, including just 0, is an octal number.
......@@ -94,7 +110,7 @@ LIBC_INLINE static int infer_base(const CharType *__restrict src,
94110// Takes a pointer to a string and the base to convert to. This function is used
95111// as the backend for all of the string to int functions.
96112template <typename T, typename CharType>
97LIBC_INLINE StrToNumResult<T>
113LIBC_INLINE constexpr StrToNumResult<T>
98114strtointeger(const CharType *__restrict src, int base,
99115 const size_t src_len = cpp::numeric_limits<size_t>::max()) {
100116 using ResultType = make_integral_or_big_int_unsigned_t<T>;
......@@ -120,6 +136,9 @@ strtointeger(const CharType *__restrict src, int base,
120136 if (base == 16 && is_hex_start(src + src_cur, src_len - src_cur))
121137 src_cur = src_cur + 2;
122138
139 if (base == 2 && is_binary_start(src + src_cur, src_len - src_cur))
140 src_cur = src_cur + 2;
141
123142 constexpr bool IS_UNSIGNED = cpp::is_unsigned_v<T>;
124143 ResultType constexpr NEGATIVE_MAX =
125144 !IS_UNSIGNED ? static_cast<ResultType>(cpp::numeric_limits<T>::max()) + 1
lib/libcxx/libc/src/__support/wctype/wctype_classification_utils.h created+66
......@@ -0,0 +1,66 @@
1//===-- Utils for wctype classification functions ---------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// DO NOT EDIT MANUALLY.
9// This file is generated by libc/utils/wctype_utils scripts.
10
11#ifndef LLVM_LIBC_SRC___SUPPORT_WCTYPE_WCTYPE_CLASSIFICATION_UTILS_H
12#define LLVM_LIBC_SRC___SUPPORT_WCTYPE_WCTYPE_CLASSIFICATION_UTILS_H
13
14#include "hdr/stdint_proxy.h"
15#include "hdr/types/wchar_t.h"
16#include "src/__support/CPP/limits.h"
17#include "src/__support/libc_assert.h"
18#include "src/__support/macros/attributes.h"
19#include "src/__support/macros/config.h"
20
21namespace LIBC_NAMESPACE_DECL {
22
23// Property flags for Unicode categories
24enum PropertyFlag : uint8_t {
25 UPPER = 1 << 0,
26 LOWER = 1 << 1,
27 ALPHA = 1 << 2,
28 SPACE = 1 << 3,
29 PRINT = 1 << 4,
30 BLANK = 1 << 5,
31 CNTRL = 1 << 6,
32 PUNCT = 1 << 7,
33};
34
35static_assert(4352 <= cpp::numeric_limits<unsigned short>::max());
36static_assert(39168 <= cpp::numeric_limits<unsigned short>::max());
37
38LIBC_INLINE_VAR constexpr uint16_t LEVEL1_SIZE = 4352;
39LIBC_INLINE_VAR constexpr uint16_t LEVEL2_SIZE = 39168;
40
41// Level 1 table: indexed by (codepoint >> 8), stores level2 block offsets
42extern const uint16_t LEVEL1[LEVEL1_SIZE];
43
44// Level 2 table: blocks of 256 property flags
45extern const uint8_t LEVEL2[LEVEL2_SIZE];
46
47// Returns the Unicode property flag for a given wide character.
48LIBC_INLINE uint8_t lookup_properties(const wchar_t wc) {
49 // Out of Unicode range
50 if (static_cast<uint32_t>(wc) > 0x10FFFF) {
51 return 0;
52 }
53
54 uint16_t l1_idx = static_cast<uint16_t>(wc >> 8);
55 LIBC_ASSERT(l1_idx < LEVEL1_SIZE);
56
57 uint16_t l2_offset = LEVEL1[l1_idx];
58 uint16_t l2_idx = l2_offset + (wc & 0xFF);
59 LIBC_ASSERT(l2_idx < LEVEL2_SIZE);
60
61 return LEVEL2[l2_idx];
62}
63
64} // namespace LIBC_NAMESPACE_DECL
65
66#endif // LLVM_LIBC_SRC___SUPPORT_WCTYPE_WCTYPE_CLASSIFICATION_UTILS_H
lib/libcxx/libc/src/__support/wctype/wctype_conversion_utils.h created+34
......@@ -0,0 +1,34 @@
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// Interface for wctype conversion functions.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_LIBC_SRC___SUPPORT_WCTYPE_WCTYPE_CONVERSION_UTILS_H
15#define LLVM_LIBC_SRC___SUPPORT_WCTYPE_WCTYPE_CONVERSION_UTILS_H
16
17#include "hdr/types/wchar_t.h"
18#include "hdr/types/wint_t.h"
19#include "src/__support/macros/attributes.h"
20#include "src/__support/macros/config.h"
21
22namespace LIBC_NAMESPACE_DECL {
23namespace wctype_internal {
24
25// Helper functions for non-ASCII case conversions.
26// These are implemented in wctype_conversion_utils.cpp using the generated
27// maps.
28wint_t tolower(wchar_t wch);
29wint_t toupper(wchar_t wch);
30
31} // namespace wctype_internal
32} // namespace LIBC_NAMESPACE_DECL
33
34#endif // LLVM_LIBC_SRC___SUPPORT_WCTYPE_WCTYPE_CONVERSION_UTILS_H
lib/libcxx/libc/src/__support/wctype_utils.h+351-137
......@@ -13,6 +13,18 @@
1313#include "src/__support/macros/attributes.h" // LIBC_INLINE
1414#include "src/__support/macros/config.h"
1515
16#define LIBC_WCTYPE_MODE_ASCII 0
17#define LIBC_WCTYPE_MODE_UTF8 1
18
19#ifndef LIBC_CONF_WCTYPE_MODE
20#define LIBC_CONF_WCTYPE_MODE LIBC_WCTYPE_MODE_ASCII
21#endif
22
23#if LIBC_CONF_WCTYPE_MODE == LIBC_WCTYPE_MODE_UTF8
24#include "src/__support/wctype/wctype_classification_utils.h"
25#include "src/__support/wctype/wctype_conversion_utils.h"
26#endif
27
1628namespace LIBC_NAMESPACE_DECL {
1729namespace internal {
1830
......@@ -38,8 +50,8 @@ namespace internal {
3850// This assumes the character ranges are contiguous, which they aren't in
3951// EBCDIC. Technically we could use some smaller ranges, but that's even harder
4052// to read.
41
42LIBC_INLINE static constexpr bool islower(wchar_t wch) {
53namespace ascii {
54LIBC_INLINE constexpr bool islower(wchar_t wch) {
4355 switch (wch) {
4456 case L'a':
4557 case L'b':
......@@ -73,7 +85,7 @@ LIBC_INLINE static constexpr bool islower(wchar_t wch) {
7385 }
7486}
7587
76LIBC_INLINE static constexpr bool isupper(wchar_t wch) {
88LIBC_INLINE constexpr bool isupper(wchar_t wch) {
7789 switch (wch) {
7890 case L'A':
7991 case L'B':
......@@ -107,7 +119,7 @@ LIBC_INLINE static constexpr bool isupper(wchar_t wch) {
107119 }
108120}
109121
110LIBC_INLINE static constexpr bool isdigit(wchar_t wch) {
122LIBC_INLINE constexpr bool isdigit(wchar_t wch) {
111123 switch (wch) {
112124 case L'0':
113125 case L'1':
......@@ -125,125 +137,169 @@ LIBC_INLINE static constexpr bool isdigit(wchar_t wch) {
125137 }
126138}
127139
128LIBC_INLINE static constexpr wchar_t tolower(wchar_t wch) {
140LIBC_INLINE constexpr bool isalpha(wchar_t wch) {
129141 switch (wch) {
142 case L'a':
143 case L'b':
144 case L'c':
145 case L'd':
146 case L'e':
147 case L'f':
148 case L'g':
149 case L'h':
150 case L'i':
151 case L'j':
152 case L'k':
153 case L'l':
154 case L'm':
155 case L'n':
156 case L'o':
157 case L'p':
158 case L'q':
159 case L'r':
160 case L's':
161 case L't':
162 case L'u':
163 case L'v':
164 case L'w':
165 case L'x':
166 case L'y':
167 case L'z':
130168 case L'A':
131 return L'a';
132169 case L'B':
133 return L'b';
134170 case L'C':
135 return L'c';
136171 case L'D':
137 return L'd';
138172 case L'E':
139 return L'e';
140173 case L'F':
141 return L'f';
142174 case L'G':
143 return L'g';
144175 case L'H':
145 return L'h';
146176 case L'I':
147 return L'i';
148177 case L'J':
149 return L'j';
150178 case L'K':
151 return L'k';
152179 case L'L':
153 return L'l';
154180 case L'M':
155 return L'm';
156181 case L'N':
157 return L'n';
158182 case L'O':
159 return L'o';
160183 case L'P':
161 return L'p';
162184 case L'Q':
163 return L'q';
164185 case L'R':
165 return L'r';
166186 case L'S':
167 return L's';
168187 case L'T':
169 return L't';
170188 case L'U':
171 return L'u';
172189 case L'V':
173 return L'v';
174190 case L'W':
175 return L'w';
176191 case L'X':
177 return L'x';
178192 case L'Y':
179 return L'y';
180193 case L'Z':
181 return L'z';
194 return true;
182195 default:
183 return wch;
196 return false;
184197 }
185198}
186199
187LIBC_INLINE static constexpr wchar_t toupper(wchar_t wch) {
200LIBC_INLINE constexpr bool isalnum(wchar_t wch) {
188201 switch (wch) {
189202 case L'a':
190 return L'A';
191203 case L'b':
192 return L'B';
193204 case L'c':
194 return L'C';
195205 case L'd':
196 return L'D';
197206 case L'e':
198 return L'E';
199207 case L'f':
200 return L'F';
201208 case L'g':
202 return L'G';
203209 case L'h':
204 return L'H';
205210 case L'i':
206 return L'I';
207211 case L'j':
208 return L'J';
209212 case L'k':
210 return L'K';
211213 case L'l':
212 return L'L';
213214 case L'm':
214 return L'M';
215215 case L'n':
216 return L'N';
217216 case L'o':
218 return L'O';
219217 case L'p':
220 return L'P';
221218 case L'q':
222 return L'Q';
223219 case L'r':
224 return L'R';
225220 case L's':
226 return L'S';
227221 case L't':
228 return L'T';
229222 case L'u':
230 return L'U';
231223 case L'v':
232 return L'V';
233224 case L'w':
234 return L'W';
235225 case L'x':
236 return L'X';
237226 case L'y':
238 return L'Y';
239227 case L'z':
240 return L'Z';
228 case L'A':
229 case L'B':
230 case L'C':
231 case L'D':
232 case L'E':
233 case L'F':
234 case L'G':
235 case L'H':
236 case L'I':
237 case L'J':
238 case L'K':
239 case L'L':
240 case L'M':
241 case L'N':
242 case L'O':
243 case L'P':
244 case L'Q':
245 case L'R':
246 case L'S':
247 case L'T':
248 case L'U':
249 case L'V':
250 case L'W':
251 case L'X':
252 case L'Y':
253 case L'Z':
254 case L'0':
255 case L'1':
256 case L'2':
257 case L'3':
258 case L'4':
259 case L'5':
260 case L'6':
261 case L'7':
262 case L'8':
263 case L'9':
264 return true;
241265 default:
242 return wch;
266 return false;
267 }
268}
269
270LIBC_INLINE constexpr bool isspace(wchar_t wch) {
271 switch (wch) {
272 case L' ':
273 case L'\t':
274 case L'\n':
275 case L'\v':
276 case L'\f':
277 case L'\r':
278 return true;
279 default:
280 return false;
281 }
282}
283
284LIBC_INLINE constexpr bool isblank(wchar_t wch) {
285 switch (wch) {
286 case L' ':
287 case L'\t':
288 return true;
289 default:
290 return false;
243291 }
244292}
245293
246LIBC_INLINE static constexpr bool isalpha(wchar_t wch) {
294LIBC_INLINE constexpr bool isgraph(wchar_t wch) {
295 return 0x20 < wch && wch < 0x7f;
296}
297
298LIBC_INLINE constexpr bool isprint(wchar_t wch) {
299 return (static_cast<unsigned>(wch) - ' ') < 95;
300}
301
302LIBC_INLINE constexpr bool isxdigit(wchar_t wch) {
247303 switch (wch) {
248304 case L'a':
249305 case L'b':
......@@ -251,129 +307,301 @@ LIBC_INLINE static constexpr bool isalpha(wchar_t wch) {
251307 case L'd':
252308 case L'e':
253309 case L'f':
254 case L'g':
255 case L'h':
256 case L'i':
257 case L'j':
258 case L'k':
259 case L'l':
260 case L'm':
261 case L'n':
262 case L'o':
263 case L'p':
264 case L'q':
265 case L'r':
266 case L's':
267 case L't':
268 case L'u':
269 case L'v':
270 case L'w':
271 case L'x':
272 case L'y':
273 case L'z':
274310 case L'A':
275311 case L'B':
276312 case L'C':
277313 case L'D':
278314 case L'E':
279315 case L'F':
316 case L'0':
317 case L'1':
318 case L'2':
319 case L'3':
320 case L'4':
321 case L'5':
322 case L'6':
323 case L'7':
324 case L'8':
325 case L'9':
326 return true;
327 default:
328 return false;
329 }
330}
331
332LIBC_INLINE constexpr bool iscntrl(wchar_t wch) {
333 return (wch < 0x20 || wch == 0x7f);
334}
335
336LIBC_INLINE constexpr bool ispunct(wchar_t wch) {
337 return !isalnum(wch) && isgraph(wch);
338}
339
340LIBC_INLINE constexpr wchar_t tolower(wchar_t wch) {
341 switch (wch) {
342 case L'A':
343 return L'a';
344 case L'B':
345 return L'b';
346 case L'C':
347 return L'c';
348 case L'D':
349 return L'd';
350 case L'E':
351 return L'e';
352 case L'F':
353 return L'f';
280354 case L'G':
355 return L'g';
281356 case L'H':
357 return L'h';
282358 case L'I':
359 return L'i';
283360 case L'J':
361 return L'j';
284362 case L'K':
363 return L'k';
285364 case L'L':
365 return L'l';
286366 case L'M':
367 return L'm';
287368 case L'N':
369 return L'n';
288370 case L'O':
371 return L'o';
289372 case L'P':
373 return L'p';
290374 case L'Q':
375 return L'q';
291376 case L'R':
377 return L'r';
292378 case L'S':
379 return L's';
293380 case L'T':
381 return L't';
294382 case L'U':
383 return L'u';
295384 case L'V':
385 return L'v';
296386 case L'W':
387 return L'w';
297388 case L'X':
389 return L'x';
298390 case L'Y':
391 return L'y';
299392 case L'Z':
300 return true;
393 return L'z';
301394 default:
302 return false;
395 return wch;
303396 }
304397}
305398
306LIBC_INLINE static constexpr bool isalnum(wchar_t wch) {
399LIBC_INLINE constexpr wchar_t toupper(wchar_t wch) {
307400 switch (wch) {
308401 case L'a':
402 return L'A';
309403 case L'b':
404 return L'B';
310405 case L'c':
406 return L'C';
311407 case L'd':
408 return L'D';
312409 case L'e':
410 return L'E';
313411 case L'f':
412 return L'F';
314413 case L'g':
414 return L'G';
315415 case L'h':
416 return L'H';
316417 case L'i':
418 return L'I';
317419 case L'j':
420 return L'J';
318421 case L'k':
422 return L'K';
319423 case L'l':
424 return L'L';
320425 case L'm':
426 return L'M';
321427 case L'n':
428 return L'N';
322429 case L'o':
430 return L'O';
323431 case L'p':
432 return L'P';
324433 case L'q':
434 return L'Q';
325435 case L'r':
436 return L'R';
326437 case L's':
438 return L'S';
327439 case L't':
440 return L'T';
328441 case L'u':
442 return L'U';
329443 case L'v':
444 return L'V';
330445 case L'w':
446 return L'W';
331447 case L'x':
448 return L'X';
332449 case L'y':
450 return L'Y';
333451 case L'z':
334 case L'A':
335 case L'B':
336 case L'C':
337 case L'D':
338 case L'E':
339 case L'F':
340 case L'G':
341 case L'H':
342 case L'I':
343 case L'J':
344 case L'K':
345 case L'L':
346 case L'M':
347 case L'N':
348 case L'O':
349 case L'P':
350 case L'Q':
351 case L'R':
352 case L'S':
353 case L'T':
354 case L'U':
355 case L'V':
356 case L'W':
357 case L'X':
358 case L'Y':
359 case L'Z':
360 case L'0':
361 case L'1':
362 case L'2':
363 case L'3':
364 case L'4':
365 case L'5':
366 case L'6':
367 case L'7':
368 case L'8':
369 case L'9':
370 return true;
452 return L'Z';
371453 default:
372 return false;
454 return wch;
455 }
456}
457
458} // namespace ascii
459
460LIBC_INLINE constexpr bool islower(wchar_t wch) {
461#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
462 return ascii::islower(wch);
463#else
464 if (static_cast<uint32_t>(wch) < 128) {
465 return ascii::islower(wch);
466 }
467 return lookup_properties(wch) & PropertyFlag::LOWER;
468#endif
469}
470
471LIBC_INLINE constexpr bool isupper(wchar_t wch) {
472#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
473 return ascii::isupper(wch);
474#else
475 if (static_cast<uint32_t>(wch) < 128) {
476 return ascii::isupper(wch);
477 }
478 return lookup_properties(wch) & PropertyFlag::UPPER;
479#endif
480}
481
482LIBC_INLINE constexpr bool isdigit(wchar_t wch) {
483 // In C.UT8, only ASCII digits are considered digits
484 return ascii::isdigit(wch);
485}
486
487LIBC_INLINE constexpr bool isalpha(wchar_t wch) {
488#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
489 return ascii::isalpha(wch);
490#else
491 if (static_cast<uint32_t>(wch) < 128) {
492 return ascii::isalpha(wch);
493 }
494 return lookup_properties(wch) & PropertyFlag::ALPHA;
495#endif
496}
497
498LIBC_INLINE constexpr bool isalnum(wchar_t wch) {
499#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
500 return ascii::isalnum(wch);
501#else
502 if (static_cast<uint32_t>(wch) < 128) {
503 return ascii::isalnum(wch);
504 }
505 // Only need to check ALPHA, digit cases are covered by ASCII path
506 return lookup_properties(wch) & PropertyFlag::ALPHA;
507#endif
508}
509
510LIBC_INLINE constexpr bool isspace(wchar_t wch) {
511#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
512 return ascii::isspace(wch);
513#else
514 if (static_cast<uint32_t>(wch) < 128) {
515 return ascii::isspace(wch);
516 }
517 return lookup_properties(wch) & PropertyFlag::SPACE;
518#endif
519}
520
521LIBC_INLINE constexpr bool isblank(wchar_t wch) {
522#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
523 return ascii::isblank(wch);
524#else
525 if (static_cast<uint32_t>(wch) < 128) {
526 return ascii::isblank(wch);
373527 }
528 return lookup_properties(wch) & PropertyFlag::BLANK;
529#endif
374530}
375531
376LIBC_INLINE static constexpr int b36_char_to_int(wchar_t wch) {
532LIBC_INLINE constexpr bool isgraph(wchar_t wch) {
533#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
534 return ascii::isgraph(wch);
535#else
536 if (static_cast<uint32_t>(wch) < 128) {
537 return ascii::isgraph(wch);
538 }
539 // print && !space
540 return (lookup_properties(wch) &
541 (PropertyFlag::PRINT | PropertyFlag::SPACE)) == PropertyFlag::PRINT;
542#endif
543}
544
545LIBC_INLINE constexpr bool isprint(wchar_t wch) {
546#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
547 return ascii::isprint(wch);
548#else
549 if (static_cast<uint32_t>(wch) < 128) {
550 return ascii::isprint(wch);
551 }
552 return lookup_properties(wch) & PropertyFlag::PRINT;
553#endif
554}
555LIBC_INLINE constexpr bool isxdigit(wchar_t wch) {
556 // Hexadecimal digits are the same in C.UTF8 as in ASCII
557 return ascii::isxdigit(wch);
558}
559
560LIBC_INLINE constexpr bool iscntrl(wchar_t wch) {
561#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
562 return ascii::iscntrl(wch);
563#else
564 if (static_cast<uint32_t>(wch) < 128) {
565 return ascii::iscntrl(wch);
566 }
567 return lookup_properties(wch) & PropertyFlag::CNTRL;
568#endif
569}
570
571LIBC_INLINE constexpr bool ispunct(wchar_t wch) {
572#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
573 return ascii::ispunct(wch);
574#else
575 if (static_cast<uint32_t>(wch) < 128) {
576 return ascii::ispunct(wch);
577 }
578 return lookup_properties(wch) & PropertyFlag::PUNCT;
579#endif
580}
581
582LIBC_INLINE constexpr wchar_t tolower(wchar_t wch) {
583#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
584 return ascii::tolower(wch);
585#else
586 if (static_cast<uint32_t>(wch) < 128) {
587 return ascii::tolower(wch);
588 }
589 return static_cast<wchar_t>(wctype_internal::tolower(wch));
590#endif
591}
592
593LIBC_INLINE constexpr wchar_t toupper(wchar_t wch) {
594#if LIBC_CONF_WCTYPE_MODE != LIBC_WCTYPE_MODE_UTF8
595 return ascii::toupper(wch);
596#else
597 if (static_cast<uint32_t>(wch) < 128) {
598 return ascii::toupper(wch);
599 }
600 return static_cast<wchar_t>(wctype_internal::toupper(wch));
601#endif
602}
603
604LIBC_INLINE constexpr int b36_char_to_int(wchar_t wch) {
377605 switch (wch) {
378606 case L'0':
379607 return 0;
......@@ -561,20 +789,6 @@ LIBC_INLINE static constexpr wchar_t int_to_b36_wchar(int num) {
561789 }
562790}
563791
564LIBC_INLINE static constexpr bool isspace(wchar_t wch) {
565 switch (wch) {
566 case L' ':
567 case L'\t':
568 case L'\n':
569 case L'\v':
570 case L'\f':
571 case L'\r':
572 return true;
573 default:
574 return false;
575 }
576}
577
578792// An overload which provides a way to compare input with specific character
579793// values, when input can be of a regular or a wide character type.
580794LIBC_INLINE static constexpr bool