[libc-commits] [libc] [libc] Implement widechar to integer public functions (PR #148683)
via libc-commits
libc-commits at lists.llvm.org
Mon Jul 14 10:31:48 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Uzair Nawaz (uzairnawaz)
<details>
<summary>Changes</summary>
Implement public wchar -> integer public functions using templated internal wcs_to_integer function
---
Patch is 33.91 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/148683.diff
17 Files Affected:
- (modified) libc/config/linux/x86_64/entrypoints.txt (+5)
- (modified) libc/include/wchar.yaml (+32)
- (modified) libc/src/wchar/CMakeLists.txt (+44)
- (added) libc/src/wchar/wcstol.cpp (+30)
- (added) libc/src/wchar/wcstol.h (+22)
- (added) libc/src/wchar/wcstoll.cpp (+30)
- (added) libc/src/wchar/wcstoll.h (+22)
- (added) libc/src/wchar/wcstoul.cpp (+30)
- (added) libc/src/wchar/wcstoul.h (+22)
- (added) libc/src/wchar/wcstoull.cpp (+30)
- (added) libc/src/wchar/wcstoull.h (+22)
- (modified) libc/test/src/wchar/CMakeLists.txt (+55)
- (added) libc/test/src/wchar/WcstolTest.h (+441)
- (added) libc/test/src/wchar/wcstol_test.cpp (+15)
- (added) libc/test/src/wchar/wcstoll_test.cpp (+15)
- (added) libc/test/src/wchar/wcstoul_test.cpp (+15)
- (added) libc/test/src/wchar/wcstoull_test.cpp (+15)
``````````diff
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index edad30634b6da..41d7ae7c66ada 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -391,6 +391,11 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.wchar.wcpcpy
libc.src.wchar.wcpncpy
libc.src.wchar.wcstok
+ libc.src.wchar.wcstol
+ libc.src.wchar.wcstoll
+ libc.src.wchar.wcstoul
+ libc.src.wchar.wcstoull
+
# sys/uio.h entrypoints
libc.src.sys.uio.writev
diff --git a/libc/include/wchar.yaml b/libc/include/wchar.yaml
index c6488fa937885..123d3440aeec3 100644
--- a/libc/include/wchar.yaml
+++ b/libc/include/wchar.yaml
@@ -242,3 +242,35 @@ functions:
- type: wchar_t *__restrict
- type: const wchar_t *__restrict
- type: size_t
+ - name: wcstol
+ standards:
+ - stdc
+ return_type: long
+ arguments:
+ - type: const wchar_t *__restrict
+ - type: wchar_t **__restrict
+ - type: int
+ - name: wcstoll
+ standards:
+ - stdc
+ return_type: long long
+ arguments:
+ - type: const wchar_t *__restrict
+ - type: wchar_t **__restrict
+ - type: int
+ - name: wcstoul
+ standards:
+ - stdc
+ return_type: unsigned long
+ arguments:
+ - type: const wchar_t *__restrict
+ - type: wchar_t **__restrict
+ - type: int
+ - name: wcstoull
+ standards:
+ - stdc
+ return_type: unsigned long long
+ arguments:
+ - type: const wchar_t *__restrict
+ - type: wchar_t **__restrict
+ - type: int
diff --git a/libc/src/wchar/CMakeLists.txt b/libc/src/wchar/CMakeLists.txt
index e3bd357a8fd1f..7ace1a6ca66ba 100644
--- a/libc/src/wchar/CMakeLists.txt
+++ b/libc/src/wchar/CMakeLists.txt
@@ -45,6 +45,50 @@ add_entrypoint_object(
libc.src.__support.wctype_utils
)
+add_entrypoint_object(
+ wcstol
+ SRCS
+ wcstol.cpp
+ HDRS
+ wcstol.h
+ DEPENDS
+ libc.src.errno.errno
+ libc.src.__support.wcs_to_integer
+)
+
+add_entrypoint_object(
+ wcstoll
+ SRCS
+ wcstoll.cpp
+ HDRS
+ wcstoll.h
+ DEPENDS
+ libc.src.errno.errno
+ libc.src.__support.wcs_to_integer
+)
+
+add_entrypoint_object(
+ wcstoul
+ SRCS
+ wcstoul.cpp
+ HDRS
+ wcstoul.h
+ DEPENDS
+ libc.src.errno.errno
+ libc.src.__support.wcs_to_integer
+)
+
+add_entrypoint_object(
+ wcstoull
+ SRCS
+ wcstoull.cpp
+ HDRS
+ wcstoull.h
+ DEPENDS
+ libc.src.errno.errno
+ libc.src.__support.wcs_to_integer
+)
+
add_entrypoint_object(
wcstok
SRCS
diff --git a/libc/src/wchar/wcstol.cpp b/libc/src/wchar/wcstol.cpp
new file mode 100644
index 0000000000000..a05718f706dfd
--- /dev/null
+++ b/libc/src/wchar/wcstol.cpp
@@ -0,0 +1,30 @@
+//===-- Implementation of wcstol ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/wchar/wcstol.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/wcs_to_integer.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(long, wcstol,
+ (const wchar_t *__restrict str, wchar_t **__restrict str_end,
+ int base)) {
+ auto result = internal::wcstointeger<long>(str, base);
+ if (result.has_error())
+ libc_errno = result.error;
+
+ if (str_end != nullptr)
+ *str_end = const_cast<wchar_t *>(str + result.parsed_len);
+
+ return result;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcstol.h b/libc/src/wchar/wcstol.h
new file mode 100644
index 0000000000000..08acd9717a237
--- /dev/null
+++ b/libc/src/wchar/wcstol.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for wcstol ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_WCHAR_WCSTOL_H
+#define LLVM_LIBC_SRC_WCHAR_WCSTOL_H
+
+#include "hdr/types/wint_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+long wcstol(const wchar_t *__restrict str, wchar_t **__restrict str_end,
+ int base);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSTOL_H
diff --git a/libc/src/wchar/wcstoll.cpp b/libc/src/wchar/wcstoll.cpp
new file mode 100644
index 0000000000000..de1299d681cdb
--- /dev/null
+++ b/libc/src/wchar/wcstoll.cpp
@@ -0,0 +1,30 @@
+//===-- Implementation of wcstoll -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/wchar/wcstoll.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/wcs_to_integer.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(long long, wcstoll,
+ (const wchar_t *__restrict str, wchar_t **__restrict str_end,
+ int base)) {
+ auto result = internal::wcstointeger<long long>(str, base);
+ if (result.has_error())
+ libc_errno = result.error;
+
+ if (str_end != nullptr)
+ *str_end = const_cast<wchar_t *>(str + result.parsed_len);
+
+ return result;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcstoll.h b/libc/src/wchar/wcstoll.h
new file mode 100644
index 0000000000000..6278043569490
--- /dev/null
+++ b/libc/src/wchar/wcstoll.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for wcstoll -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_WCHAR_WCSTOLL_H
+#define LLVM_LIBC_SRC_WCHAR_WCSTOLL_H
+
+#include "hdr/types/wint_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+long long wcstoll(const wchar_t *__restrict str, wchar_t **__restrict str_end,
+ int base);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSTOLL_H
diff --git a/libc/src/wchar/wcstoul.cpp b/libc/src/wchar/wcstoul.cpp
new file mode 100644
index 0000000000000..79b8c9b5c9fa3
--- /dev/null
+++ b/libc/src/wchar/wcstoul.cpp
@@ -0,0 +1,30 @@
+//===-- Implementation of wcstoul -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/wchar/wcstoul.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/wcs_to_integer.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(unsigned long, wcstoul,
+ (const wchar_t *__restrict str, wchar_t **__restrict str_end,
+ int base)) {
+ auto result = internal::wcstointeger<unsigned long>(str, base);
+ if (result.has_error())
+ libc_errno = result.error;
+
+ if (str_end != nullptr)
+ *str_end = const_cast<wchar_t *>(str + result.parsed_len);
+
+ return result;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcstoul.h b/libc/src/wchar/wcstoul.h
new file mode 100644
index 0000000000000..81f530534e81a
--- /dev/null
+++ b/libc/src/wchar/wcstoul.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for wcstoul -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_WCHAR_WCSTOUL_H
+#define LLVM_LIBC_SRC_WCHAR_WCSTOUL_H
+
+#include "hdr/types/wint_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned long wcstoul(const wchar_t *__restrict str,
+ wchar_t **__restrict str_end, int base);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSTOUL_H
diff --git a/libc/src/wchar/wcstoull.cpp b/libc/src/wchar/wcstoull.cpp
new file mode 100644
index 0000000000000..768e03c4bd189
--- /dev/null
+++ b/libc/src/wchar/wcstoull.cpp
@@ -0,0 +1,30 @@
+//===-- Implementation of wcstoull ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/wchar/wcstoull.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/wcs_to_integer.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(unsigned long long, wcstoull,
+ (const wchar_t *__restrict str, wchar_t **__restrict str_end,
+ int base)) {
+ auto result = internal::wcstointeger<unsigned long long>(str, base);
+ if (result.has_error())
+ libc_errno = result.error;
+
+ if (str_end != nullptr)
+ *str_end = const_cast<wchar_t *>(str + result.parsed_len);
+
+ return result;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/wchar/wcstoull.h b/libc/src/wchar/wcstoull.h
new file mode 100644
index 0000000000000..e970a5792338b
--- /dev/null
+++ b/libc/src/wchar/wcstoull.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for wcstoull -----------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_WCHAR_WCSTOULL_H
+#define LLVM_LIBC_SRC_WCHAR_WCSTOULL_H
+
+#include "hdr/types/wint_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned long long wcstoull(const wchar_t *__restrict str,
+ wchar_t **__restrict str_end, int base);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_WCHAR_WCSTOULL_H
diff --git a/libc/test/src/wchar/CMakeLists.txt b/libc/test/src/wchar/CMakeLists.txt
index dc233fca59741..176cf7c3487cd 100644
--- a/libc/test/src/wchar/CMakeLists.txt
+++ b/libc/test/src/wchar/CMakeLists.txt
@@ -334,3 +334,58 @@ add_libc_test(
DEPENDS
libc.src.wchar.wcpncpy
)
+
+add_header_library(
+ wcstol_test_support
+ HDRS
+ WcstolTest.h
+ DEPENDS
+ libc.src.__support.CPP.limits
+ libc.src.__support.CPP.type_traits
+ libc.src.errno.errno
+ libc.test.UnitTest.ErrnoCheckingTest
+)
+
+add_libc_test(
+ wcstol_test
+ SUITE
+ libc_wchar_unittests
+ SRCS
+ wcstol_test.cpp
+ DEPENDS
+ libc.src.wchar.wcstol
+ .wcstol_test_support
+)
+
+add_libc_test(
+ wcstoll_test
+ SUITE
+ libc_wchar_unittests
+ SRCS
+ wcstoll_test.cpp
+ DEPENDS
+ libc.src.wchar.wcstoll
+ .wcstol_test_support
+)
+
+add_libc_test(
+ wcstoul_test
+ SUITE
+ libc_wchar_unittests
+ SRCS
+ wcstoul_test.cpp
+ DEPENDS
+ libc.src.wchar.wcstoul
+ .wcstol_test_support
+)
+
+add_libc_test(
+ wcstoull_test
+ SUITE
+ libc_wchar_unittests
+ SRCS
+ wcstoull_test.cpp
+ DEPENDS
+ libc.src.wchar.wcstoull
+ .wcstol_test_support
+)
\ No newline at end of file
diff --git a/libc/test/src/wchar/WcstolTest.h b/libc/test/src/wchar/WcstolTest.h
new file mode 100644
index 0000000000000..8a4294ace41cb
--- /dev/null
+++ b/libc/test/src/wchar/WcstolTest.h
@@ -0,0 +1,441 @@
+//===-- A template class for testing wcsto* functions -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/CPP/limits.h"
+#include "src/__support/CPP/type_traits.h"
+#include "src/__support/macros/properties/architectures.h"
+#include "src/__support/wctype_utils.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/Test.h"
+
+#include <stddef.h>
+
+using LIBC_NAMESPACE::cpp::is_signed_v;
+
+template <typename ReturnT>
+struct WcstoTest : public LIBC_NAMESPACE::testing::ErrnoCheckingTest {
+ using FunctionT = ReturnT (*)(const wchar_t *, wchar_t **, int);
+
+ static constexpr ReturnT T_MAX =
+ LIBC_NAMESPACE::cpp::numeric_limits<ReturnT>::max();
+ static constexpr ReturnT T_MIN =
+ LIBC_NAMESPACE::cpp::numeric_limits<ReturnT>::min();
+
+ void InvalidBase(FunctionT func) {
+ const wchar_t *ten = L"10";
+ ASSERT_EQ(func(ten, nullptr, -1), ReturnT(0));
+ ASSERT_ERRNO_EQ(EINVAL);
+ }
+
+ void CleanBaseTenDecode(FunctionT func) {
+ wchar_t *str_end = nullptr;
+
+ // TODO: Look into collapsing these repeated segments.
+ const wchar_t *ten = L"10";
+ ASSERT_EQ(func(ten, &str_end, 10), ReturnT(10));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - ten, ptrdiff_t(2));
+
+ ASSERT_EQ(func(ten, nullptr, 10), ReturnT(10));
+ ASSERT_ERRNO_SUCCESS();
+
+ const wchar_t *hundred = L"100";
+ ASSERT_EQ(func(hundred, &str_end, 10), ReturnT(100));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - hundred, ptrdiff_t(3));
+
+ const wchar_t *big_number = L"1234567890";
+ ASSERT_EQ(func(big_number, &str_end, 10), ReturnT(1234567890));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - big_number, ptrdiff_t(10));
+
+ // This number is larger than 2^32, meaning that if long is only 32 bits
+ // wide, strtol will return LONG_MAX.
+ const wchar_t *bigger_number = L"12345678900";
+ if constexpr (sizeof(ReturnT) < 8) {
+ ASSERT_EQ(func(bigger_number, &str_end, 10), T_MAX);
+ ASSERT_ERRNO_EQ(ERANGE);
+ } else {
+ ASSERT_EQ(func(bigger_number, &str_end, 10), ReturnT(12345678900));
+ ASSERT_ERRNO_SUCCESS();
+ }
+ EXPECT_EQ(str_end - bigger_number, ptrdiff_t(11));
+
+ const wchar_t *too_big_number = L"123456789012345678901";
+ ASSERT_EQ(func(too_big_number, &str_end, 10), T_MAX);
+ ASSERT_ERRNO_EQ(ERANGE);
+ EXPECT_EQ(str_end - too_big_number, ptrdiff_t(21));
+
+ const wchar_t *long_number_range_test =
+ L"10000000000000000000000000000000000000000000000000";
+ ASSERT_EQ(func(long_number_range_test, &str_end, 10), T_MAX);
+ ASSERT_ERRNO_EQ(ERANGE);
+ EXPECT_EQ(str_end - long_number_range_test, ptrdiff_t(50));
+
+ // For most negative numbers, the unsigned functions treat it the same as
+ // casting a negative variable to an unsigned type.
+ const wchar_t *negative = L"-100";
+ ASSERT_EQ(func(negative, &str_end, 10), ReturnT(-100));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - negative, ptrdiff_t(4));
+
+ const wchar_t *big_negative_number = L"-1234567890";
+ ASSERT_EQ(func(big_negative_number, &str_end, 10), ReturnT(-1234567890));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - big_negative_number, ptrdiff_t(11));
+
+ const wchar_t *too_big_negative_number = L"-123456789012345678901";
+ // If the number is signed, it should return the smallest negative number
+ // for the current type, but if it's unsigned it should max out and return
+ // the largest positive number for the current type. From the standard:
+ // "If the correct value is outside the range of representable values,
+ // LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, or ULLONG_MAX is
+ // returned"
+ // Note that 0 is not on that list.
+ ASSERT_EQ(func(too_big_negative_number, &str_end, 10),
+ (is_signed_v<ReturnT> ? T_MIN : T_MAX));
+ ASSERT_ERRNO_EQ(ERANGE);
+ EXPECT_EQ(str_end - too_big_negative_number, ptrdiff_t(22));
+ }
+
+ void MessyBaseTenDecode(FunctionT func) {
+ wchar_t *str_end = nullptr;
+
+ const wchar_t *spaces_before = L" 10";
+ ASSERT_EQ(func(spaces_before, &str_end, 10), ReturnT(10));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - spaces_before, ptrdiff_t(7));
+
+ const wchar_t *spaces_after = L"10 ";
+ ASSERT_EQ(func(spaces_after, &str_end, 10), ReturnT(10));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - spaces_after, ptrdiff_t(2));
+
+ const wchar_t *word_before = L"word10";
+ ASSERT_EQ(func(word_before, &str_end, 10), ReturnT(0));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - word_before, ptrdiff_t(0));
+
+ const wchar_t *word_after = L"10word";
+ ASSERT_EQ(func(word_after, &str_end, 10), ReturnT(10));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - word_after, ptrdiff_t(2));
+
+ const wchar_t *two_numbers = L"10 999";
+ ASSERT_EQ(func(two_numbers, &str_end, 10), ReturnT(10));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - two_numbers, ptrdiff_t(2));
+
+ const wchar_t *two_signs = L"--10 999";
+ ASSERT_EQ(func(two_signs, &str_end, 10), ReturnT(0));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - two_signs, ptrdiff_t(0));
+
+ const wchar_t *sign_before = L"+2=4";
+ ASSERT_EQ(func(sign_before, &str_end, 10), ReturnT(2));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - sign_before, ptrdiff_t(2));
+
+ const wchar_t *sign_after = L"2+2=4";
+ ASSERT_EQ(func(sign_after, &str_end, 10), ReturnT(2));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - sign_after, ptrdiff_t(1));
+
+ const wchar_t *tab_before = L"\t10";
+ ASSERT_EQ(func(tab_before, &str_end, 10), ReturnT(10));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - tab_before, ptrdiff_t(3));
+
+ const wchar_t *all_together = L"\t -12345and+67890";
+ ASSERT_EQ(func(all_together, &str_end, 10), ReturnT(-12345));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - all_together, ptrdiff_t(9));
+
+ const wchar_t *just_spaces = L" ";
+ ASSERT_EQ(func(just_spaces, &str_end, 10), ReturnT(0));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - just_spaces, ptrdiff_t(0));
+
+ const wchar_t *just_space_and_sign = L" +";
+ ASSERT_EQ(func(just_space_and_sign, &str_end, 10), ReturnT(0));
+ ASSERT_ERRNO_SUCCESS();
+ EXPECT_EQ(str_end - just_space_and_sign, ptrdiff_t(0));
+ }
+
+ void DecodeInOtherBases(FunctionT func) {
+ // This test is excessively slow on the GPU, so we limit the innermost loop.
+#if defined(LIBC_TARGET_ARCH_IS_GPU)
+ constexpr int limit = 0;
+#else
+ constexpr int limit = 36;
+#endif
+ wchar_t small_string[4] = {L'\0', L'\0', L'\0', L'\0'};
+ for (int base = 2; base <= 36; ++base) {
+ for (int first_digit = 0; first_digit <= 36; ++first_digit) {
+ small_string[0] = static_cast<wchar_t>(
+ LIBC_NAMESPACE::internal::int_to_b36_wchar(first_digit));
+ if (first_digit < base) {
+ ASSERT_EQ(func(small_string, nullptr, base),
+ static_cast<ReturnT>(first_digit));
+ ASSERT_ERRNO_SUCCESS();
+ } else {
+ ASSERT_EQ(func(small_string, nullptr, base), ReturnT(0));
+ ASSERT_ERRNO_SUCCESS();
+ }
+ }
+ }
+
+ for (int base = 2; base <= 36; ++base) {
+ for (int first_digit = 0; first_digit <= 36; ++first_digit) {
+ small_string[0] = static_cast<wchar_t>(
+ LIBC_NAMESPACE::internal::int_to_b36_wchar(first_digit));
+ for ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/148683
More information about the libc-commits
mailing list