diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -158,7 +158,10 @@ libc.src.stdlib.abs libc.src.stdlib.labs libc.src.stdlib.llabs + libc.src.stdlib.strtol libc.src.stdlib.strtoll + libc.src.stdlib.strtoul + libc.src.stdlib.strtoull # signal.h entrypoints libc.src.signal.raise diff --git a/libc/spec/spec.td b/libc/spec/spec.td --- a/libc/spec/spec.td +++ b/libc/spec/spec.td @@ -40,7 +40,9 @@ def VoidType : NamedType<"void">; def IntType : NamedType<"int">; def LongType : NamedType<"long">; +def UnsignedLongType : NamedType<"unsigned long">; def LongLongType : NamedType<"long long">; +def UnsignedLongLongType : NamedType<"unsigned long long">; def FloatType : NamedType<"float">; def DoubleType : NamedType<"double">; def LongDoubleType : NamedType<"long double">; diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -478,7 +478,10 @@ FunctionSpec<"abs", RetValSpec, [ArgSpec]>, FunctionSpec<"labs", RetValSpec, [ArgSpec]>, FunctionSpec<"llabs", RetValSpec, [ArgSpec]>, + FunctionSpec<"strtol", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"strtoll", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"strtoul", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, + FunctionSpec<"strtoull", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"_Exit", RetValSpec, [ArgSpec]>, ] >; diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -20,6 +20,7 @@ .ctype_utils libc.include.errno libc.src.errno.__errno_location + libc.utils.CPP.standalone_cpp ) add_header_library( diff --git a/libc/src/__support/str_conv_utils.h b/libc/src/__support/str_conv_utils.h --- a/libc/src/__support/str_conv_utils.h +++ b/libc/src/__support/str_conv_utils.h @@ -10,6 +10,7 @@ #define LIBC_SRC_STDLIB_STDLIB_UTILS_H #include "src/__support/ctype_utils.h" +#include "utils/CPP/Limits.h" #include #include @@ -50,8 +51,9 @@ // Takes a pointer to a string, a pointer to a string pointer, and the base to // convert to. This function is used as the backend for all of the string to int // functions. -static inline long long strtoll(const char *__restrict src, - char **__restrict str_end, int base) { +template +static inline T strtointeger(const char *__restrict src, + char **__restrict str_end, int base) { unsigned long long result = 0; if (base < 0 || base == 1 || base > 36) { @@ -73,36 +75,56 @@ src = src + 2; } + constexpr bool is_unsigned = (__llvm_libc::cpp::NumericLimits::min() == 0); + const bool is_positive = (result_sign == '+'); + unsigned long long constexpr NEGATIVE_MAX = + !is_unsigned ? static_cast( + __llvm_libc::cpp::NumericLimits::max()) + + 1 + : __llvm_libc::cpp::NumericLimits::max(); unsigned long long const ABS_MAX = - (result_sign == '+' ? LLONG_MAX - : static_cast(LLONG_MAX) + 1); + (is_positive ? __llvm_libc::cpp::NumericLimits::max() : NEGATIVE_MAX); unsigned long long const ABS_MAX_DIV_BY_BASE = ABS_MAX / base; while (isalnum(*src)) { int cur_digit = b36_char_to_int(*src); if (cur_digit >= base) break; + + ++src; + + // If the number has already hit the maximum value for the current type then + // the result cannot change, but we still need to advance src to the end of + // the number. + if (result == ABS_MAX) { + errno = ERANGE; // NOLINT + continue; + } + if (result > ABS_MAX_DIV_BY_BASE) { result = ABS_MAX; errno = ERANGE; // NOLINT - break; + } else { + result = result * base; } - result = result * base; if (result > ABS_MAX - cur_digit) { result = ABS_MAX; errno = ERANGE; // NOLINT - break; + } else { + result = result + cur_digit; } - result = result + cur_digit; - - ++src; } if (str_end != nullptr) *str_end = const_cast(src); - if (result_sign == '+') - return result; - else - return -result; + + if (result == ABS_MAX) { + if (is_positive || is_unsigned) + return __llvm_libc::cpp::NumericLimits::max(); + else // T is signed and there is a negative overflow + return __llvm_libc::cpp::NumericLimits::min(); + } + + return is_positive ? static_cast(result) : -static_cast(result); } } // namespace internal diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt --- a/libc/src/stdlib/CMakeLists.txt +++ b/libc/src/stdlib/CMakeLists.txt @@ -51,6 +51,16 @@ libc.src.__support.integer_operations ) +add_entrypoint_object( + strtol + SRCS + strtol.cpp + HDRS + strtol.h + DEPENDS + libc.src.__support.str_conv_utils +) + add_entrypoint_object( strtoll SRCS @@ -60,3 +70,23 @@ DEPENDS libc.src.__support.str_conv_utils ) + +add_entrypoint_object( + strtoul + SRCS + strtoul.cpp + HDRS + strtoul.h + DEPENDS + libc.src.__support.str_conv_utils +) + +add_entrypoint_object( + strtoull + SRCS + strtoull.cpp + HDRS + strtoull.h + DEPENDS + libc.src.__support.str_conv_utils +) diff --git a/libc/src/stdlib/strtol.h b/libc/src/stdlib/strtol.h new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/strtol.h @@ -0,0 +1,18 @@ +//===-- Implementation header for strtol ------------------------*- 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_STDLIB_STRTOL_H +#define LLVM_LIBC_SRC_STDLIB_STRTOL_H + +namespace __llvm_libc { + +long strtol(const char *__restrict str, char **__restrict str_end, int base); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDLIB_STRTOL_H diff --git a/libc/src/stdlib/strtoll.cpp b/libc/src/stdlib/strtol.cpp copy from libc/src/stdlib/strtoll.cpp copy to libc/src/stdlib/strtol.cpp --- a/libc/src/stdlib/strtoll.cpp +++ b/libc/src/stdlib/strtol.cpp @@ -1,4 +1,4 @@ -//===-- Implementation of strtoll -----------------------------------------===// +//===-- Implementation of strtol ------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,16 +6,16 @@ // //===----------------------------------------------------------------------===// -#include "src/stdlib/strtoll.h" +#include "src/stdlib/strtol.h" #include "src/__support/common.h" #include "src/__support/str_conv_utils.h" namespace __llvm_libc { -LLVM_LIBC_FUNCTION(long long, strtoll, +LLVM_LIBC_FUNCTION(long, strtol, (const char *__restrict str, char **__restrict str_end, int base)) { - return internal::strtoll(str, str_end, base); + return internal::strtointeger(str, str_end, base); } } // namespace __llvm_libc diff --git a/libc/src/stdlib/strtoll.cpp b/libc/src/stdlib/strtoll.cpp --- a/libc/src/stdlib/strtoll.cpp +++ b/libc/src/stdlib/strtoll.cpp @@ -15,7 +15,7 @@ LLVM_LIBC_FUNCTION(long long, strtoll, (const char *__restrict str, char **__restrict str_end, int base)) { - return internal::strtoll(str, str_end, base); + return internal::strtointeger(str, str_end, base); } } // namespace __llvm_libc diff --git a/libc/src/stdlib/strtoul.h b/libc/src/stdlib/strtoul.h new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/strtoul.h @@ -0,0 +1,19 @@ +//===-- Implementation header for strtoul -----------------------*- 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_STDLIB_STRTOUL_H +#define LLVM_LIBC_SRC_STDLIB_STRTOUL_H + +namespace __llvm_libc { + +unsigned long strtoul(const char *__restrict str, char **__restrict str_end, + int base); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDLIB_STRTOUL_H diff --git a/libc/src/stdlib/strtoll.cpp b/libc/src/stdlib/strtoul.cpp copy from libc/src/stdlib/strtoll.cpp copy to libc/src/stdlib/strtoul.cpp --- a/libc/src/stdlib/strtoll.cpp +++ b/libc/src/stdlib/strtoul.cpp @@ -1,4 +1,4 @@ -//===-- Implementation of strtoll -----------------------------------------===// +//===-- Implementation of strtoul -----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,16 +6,16 @@ // //===----------------------------------------------------------------------===// -#include "src/stdlib/strtoll.h" +#include "src/stdlib/strtoul.h" #include "src/__support/common.h" #include "src/__support/str_conv_utils.h" namespace __llvm_libc { -LLVM_LIBC_FUNCTION(long long, strtoll, +LLVM_LIBC_FUNCTION(unsigned long, strtoul, (const char *__restrict str, char **__restrict str_end, int base)) { - return internal::strtoll(str, str_end, base); + return internal::strtointeger(str, str_end, base); } } // namespace __llvm_libc diff --git a/libc/src/stdlib/strtoull.h b/libc/src/stdlib/strtoull.h new file mode 100644 --- /dev/null +++ b/libc/src/stdlib/strtoull.h @@ -0,0 +1,19 @@ +//===-- Implementation header for strtoull ----------------------*- 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_STDLIB_STRTOULL_H +#define LLVM_LIBC_SRC_STDLIB_STRTOULL_H + +namespace __llvm_libc { + +unsigned long long strtoull(const char *__restrict str, + char **__restrict str_end, int base); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STDLIB_STRTOULL_H diff --git a/libc/src/stdlib/strtoll.cpp b/libc/src/stdlib/strtoull.cpp copy from libc/src/stdlib/strtoll.cpp copy to libc/src/stdlib/strtoull.cpp --- a/libc/src/stdlib/strtoll.cpp +++ b/libc/src/stdlib/strtoull.cpp @@ -1,4 +1,4 @@ -//===-- Implementation of strtoll -----------------------------------------===// +//===-- Implementation of strtoull ----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,16 +6,16 @@ // //===----------------------------------------------------------------------===// -#include "src/stdlib/strtoll.h" +#include "src/stdlib/strtoull.h" #include "src/__support/common.h" #include "src/__support/str_conv_utils.h" namespace __llvm_libc { -LLVM_LIBC_FUNCTION(long long, strtoll, +LLVM_LIBC_FUNCTION(unsigned long long, strtoull, (const char *__restrict str, char **__restrict str_end, int base)) { - return internal::strtoll(str, str_end, base); + return internal::strtointeger(str, str_end, base); } } // namespace __llvm_libc diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt --- a/libc/test/src/stdlib/CMakeLists.txt +++ b/libc/test/src/stdlib/CMakeLists.txt @@ -55,6 +55,16 @@ libc.src.stdlib.llabs ) +add_libc_unittest( + strtol_test + SUITE + libc_stdlib_unittests + SRCS + strtol_test.cpp + DEPENDS + libc.src.stdlib.strtol +) + add_libc_unittest( strtoll_test SUITE @@ -63,6 +73,24 @@ strtoll_test.cpp DEPENDS libc.src.stdlib.strtoll - libc.include.errno - libc.test.errno_setter_matcher +) + +add_libc_unittest( + strtoul_test + SUITE + libc_stdlib_unittests + SRCS + strtoul_test.cpp + DEPENDS + libc.src.stdlib.strtoul +) + +add_libc_unittest( + strtoull_test + SUITE + libc_stdlib_unittests + SRCS + strtoull_test.cpp + DEPENDS + libc.src.stdlib.strtoull ) diff --git a/libc/test/src/stdlib/strtoll_test.cpp b/libc/test/src/stdlib/strtol_test.cpp copy from libc/test/src/stdlib/strtoll_test.cpp copy to libc/test/src/stdlib/strtol_test.cpp --- a/libc/test/src/stdlib/strtoll_test.cpp +++ b/libc/test/src/stdlib/strtol_test.cpp @@ -1,4 +1,4 @@ -//===-- Unittests for strtoll ---------------------------------------------===// +//===-- Unittests for strtol ---------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,131 +6,139 @@ // //===----------------------------------------------------------------------===// -#include "src/stdlib/strtoll.h" +#include "src/stdlib/strtol.h" #include "utils/UnitTest/Test.h" #include #include -TEST(LlvmLibcStrToLLTest, InvalidBase) { +TEST(LlvmLibcStrToLTest, InvalidBase) { const char *ten = "10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(ten, nullptr, -1), 0ll); + ASSERT_EQ(__llvm_libc::strtol(ten, nullptr, -1), 0l); ASSERT_EQ(errno, EINVAL); } -TEST(LlvmLibcStrToLLTest, CleanBaseTenDecode) { +TEST(LlvmLibcStrToLTest, CleanBaseTenDecode) { char *str_end = nullptr; const char *ten = "10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(ten, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtol(ten, &str_end, 10), 10l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - ten, 2l); errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(ten, nullptr, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtol(ten, nullptr, 10), 10l); ASSERT_EQ(errno, 0); const char *hundred = "100"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(hundred, &str_end, 10), 100ll); + ASSERT_EQ(__llvm_libc::strtol(hundred, &str_end, 10), 100l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - hundred, 3l); const char *negative = "-100"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(negative, &str_end, 10), -100ll); + ASSERT_EQ(__llvm_libc::strtol(negative, &str_end, 10), -100l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - negative, 4l); const char *big_number = "123456789012345"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(big_number, &str_end, 10), 123456789012345ll); + ASSERT_EQ(__llvm_libc::strtol(big_number, &str_end, 10), 123456789012345l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - big_number, 15l); const char *big_negative_number = "-123456789012345"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(big_negative_number, &str_end, 10), - -123456789012345ll); + ASSERT_EQ(__llvm_libc::strtol(big_negative_number, &str_end, 10), + -123456789012345l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - big_negative_number, 16l); const char *too_big_number = "123456789012345678901"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(too_big_number, &str_end, 10), LLONG_MAX); + ASSERT_EQ(__llvm_libc::strtol(too_big_number, &str_end, 10), LONG_MAX); ASSERT_EQ(errno, ERANGE); - EXPECT_EQ(str_end - too_big_number, 19l); + EXPECT_EQ(str_end - too_big_number, 21l); const char *too_big_negative_number = "-123456789012345678901"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(too_big_negative_number, &str_end, 10), - LLONG_MIN); + ASSERT_EQ(__llvm_libc::strtol(too_big_negative_number, &str_end, 10), + LONG_MIN); ASSERT_EQ(errno, ERANGE); - EXPECT_EQ(str_end - too_big_negative_number, 20l); + EXPECT_EQ(str_end - too_big_negative_number, 22l); + + const char *long_number_range_test = + "10000000000000000000000000000000000000000000000000"; + errno = 0; + ASSERT_EQ(__llvm_libc::strtol(long_number_range_test, &str_end, 10), + LONG_MAX); + ASSERT_EQ(errno, ERANGE); + EXPECT_EQ(str_end - long_number_range_test, 50l); } -TEST(LlvmLibcStrToLLTest, MessyBaseTenDecode) { +TEST(LlvmLibcStrToLTest, MessyBaseTenDecode) { char *str_end = nullptr; const char *spaces_before = " 10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(spaces_before, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtol(spaces_before, &str_end, 10), 10l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - spaces_before, 7l); const char *spaces_after = "10 "; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(spaces_after, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtol(spaces_after, &str_end, 10), 10l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - spaces_after, 2l); const char *word_before = "word10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(word_before, &str_end, 10), 0ll); + ASSERT_EQ(__llvm_libc::strtol(word_before, &str_end, 10), 0l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - word_before, 0l); const char *word_after = "10word"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(word_after, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtol(word_after, &str_end, 10), 10l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - word_after, 2l); const char *two_numbers = "10 999"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(two_numbers, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtol(two_numbers, &str_end, 10), 10l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - two_numbers, 2l); const char *two_signs = "--10 999"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(two_signs, &str_end, 10), 0ll); + ASSERT_EQ(__llvm_libc::strtol(two_signs, &str_end, 10), 0l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - two_signs, 1l); const char *sign_before = "+2=4"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(sign_before, &str_end, 10), 2ll); + ASSERT_EQ(__llvm_libc::strtol(sign_before, &str_end, 10), 2l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - sign_before, 2l); const char *sign_after = "2+2=4"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(sign_after, &str_end, 10), 2ll); + ASSERT_EQ(__llvm_libc::strtol(sign_after, &str_end, 10), 2l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - sign_after, 1l); const char *tab_before = "\t10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(tab_before, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtol(tab_before, &str_end, 10), 10l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - tab_before, 3l); const char *all_together = "\t -12345and+67890"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(all_together, &str_end, 10), -12345ll); + ASSERT_EQ(__llvm_libc::strtol(all_together, &str_end, 10), -12345l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - all_together, 9l); } @@ -143,65 +151,65 @@ return 'A' + input - 10; } -TEST(LlvmLibcStrToLLTest, DecodeInOtherBases) { +TEST(LlvmLibcStrToLTest, DecodeInOtherBases) { char small_string[4] = {'\0', '\0', '\0', '\0'}; - for (int base = 2; base <= 36; ++base) { - for (long long first_digit = 0; first_digit <= 36; ++first_digit) { + for (unsigned int base = 2; base <= 36; ++base) { + for (long first_digit = 0; first_digit <= 36; ++first_digit) { small_string[0] = int_to_b36_char(first_digit); if (first_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), first_digit); ASSERT_EQ(errno, 0); } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), 0ll); + ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), 0l); ASSERT_EQ(errno, 0); } } } - for (int base = 2; base <= 36; ++base) { - for (long long first_digit = 0; first_digit <= 36; ++first_digit) { + for (unsigned int base = 2; base <= 36; ++base) { + for (long first_digit = 0; first_digit <= 36; ++first_digit) { small_string[0] = int_to_b36_char(first_digit); - for (long long second_digit = 0; second_digit <= 36; ++second_digit) { + for (long second_digit = 0; second_digit <= 36; ++second_digit) { small_string[1] = int_to_b36_char(second_digit); if (first_digit < base && second_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), second_digit + (first_digit * base)); ASSERT_EQ(errno, 0); } else if (first_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), first_digit); ASSERT_EQ(errno, 0); } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), 0ll); + ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), 0l); ASSERT_EQ(errno, 0); } } } } - for (int base = 2; base <= 36; ++base) { - for (long long first_digit = 0; first_digit <= 36; ++first_digit) { + for (unsigned int base = 2; base <= 36; ++base) { + for (long first_digit = 0; first_digit <= 36; ++first_digit) { small_string[0] = int_to_b36_char(first_digit); - for (long long second_digit = 0; second_digit <= 36; ++second_digit) { + for (long second_digit = 0; second_digit <= 36; ++second_digit) { small_string[1] = int_to_b36_char(second_digit); - for (long long third_digit = 0; third_digit <= 36; ++third_digit) { + for (long third_digit = 0; third_digit <= 36; ++third_digit) { small_string[2] = int_to_b36_char(third_digit); if (first_digit < base && second_digit < base && third_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), third_digit + (second_digit * base) + (first_digit * base * base)); ASSERT_EQ(errno, 0); } else if (first_digit < base && second_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), second_digit + (first_digit * base)); ASSERT_EQ(errno, 0); } else if (first_digit < base) { @@ -210,24 +218,23 @@ if (base == 16 && first_digit == 0 && second_digit == 33) { if (third_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), third_digit); ASSERT_EQ(errno, 0); } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), - 0ll); + ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), 0l); ASSERT_EQ(errno, 0); } } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), first_digit); ASSERT_EQ(errno, 0); } } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), 0ll); + ASSERT_EQ(__llvm_libc::strtol(small_string, nullptr, base), 0l); ASSERT_EQ(errno, 0); } } @@ -236,48 +243,47 @@ } } -TEST(LlvmLibcStrToLLTest, CleanBaseSixteenDecode) { +TEST(LlvmLibcStrToLTest, CleanBaseSixteenDecode) { char *str_end = nullptr; const char *no_prefix = "123abc"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(no_prefix, &str_end, 16), 0x123abcll); + ASSERT_EQ(__llvm_libc::strtol(no_prefix, &str_end, 16), 0x123abcl); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - no_prefix, 6l); const char *yes_prefix = "0x456def"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(yes_prefix, &str_end, 16), 0x456defll); + ASSERT_EQ(__llvm_libc::strtol(yes_prefix, &str_end, 16), 0x456defl); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - yes_prefix, 8l); } -TEST(LlvmLibcStrToLLTest, AutomaticBaseSelection) { +TEST(LlvmLibcStrToLTest, AutomaticBaseSelection) { char *str_end = nullptr; const char *base_ten = "12345"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(base_ten, &str_end, 0), 12345ll); + ASSERT_EQ(__llvm_libc::strtol(base_ten, &str_end, 0), 12345l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - base_ten, 5l); const char *base_sixteen_no_prefix = "123abc"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(base_sixteen_no_prefix, &str_end, 0), 123ll); + ASSERT_EQ(__llvm_libc::strtol(base_sixteen_no_prefix, &str_end, 0), 123l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - base_sixteen_no_prefix, 3l); const char *base_sixteen_with_prefix = "0x456def"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(base_sixteen_with_prefix, &str_end, 0), - 0x456defll); + ASSERT_EQ(__llvm_libc::strtol(base_sixteen_with_prefix, &str_end, 0), + 0x456defl); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - base_sixteen_with_prefix, 8l); const char *base_eight_with_prefix = "012345"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(base_eight_with_prefix, &str_end, 0), - 012345ll); + ASSERT_EQ(__llvm_libc::strtol(base_eight_with_prefix, &str_end, 0), 012345l); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - base_eight_with_prefix, 6l); } diff --git a/libc/test/src/stdlib/strtoll_test.cpp b/libc/test/src/stdlib/strtoll_test.cpp --- a/libc/test/src/stdlib/strtoll_test.cpp +++ b/libc/test/src/stdlib/strtoll_test.cpp @@ -57,18 +57,49 @@ ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - big_negative_number, 16l); + const char *long_long_max_number = "9223372036854775807"; + errno = 0; + ASSERT_EQ(__llvm_libc::strtoll(long_long_max_number, &str_end, 10), + 9223372036854775807ll); + ASSERT_EQ(errno, 0); + EXPECT_EQ(str_end - long_long_max_number, 19l); + + const char *long_long_min_number = "-9223372036854775808"; + errno = 0; + ASSERT_EQ(__llvm_libc::strtoll(long_long_min_number, &str_end, 10), + -9223372036854775807ll - 1ll); + ASSERT_EQ(errno, 0); + EXPECT_EQ(str_end - long_long_min_number, 20l); + const char *too_big_number = "123456789012345678901"; errno = 0; ASSERT_EQ(__llvm_libc::strtoll(too_big_number, &str_end, 10), LLONG_MAX); ASSERT_EQ(errno, ERANGE); - EXPECT_EQ(str_end - too_big_number, 19l); + EXPECT_EQ(str_end - too_big_number, 21l); const char *too_big_negative_number = "-123456789012345678901"; errno = 0; ASSERT_EQ(__llvm_libc::strtoll(too_big_negative_number, &str_end, 10), LLONG_MIN); ASSERT_EQ(errno, ERANGE); - EXPECT_EQ(str_end - too_big_negative_number, 20l); + EXPECT_EQ(str_end - too_big_negative_number, 22l); + + const char *long_number_range_test = + "10000000000000000000000000000000000000000000000000"; + errno = 0; + ASSERT_EQ(__llvm_libc::strtoll(long_number_range_test, &str_end, 10), + LLONG_MAX); + ASSERT_EQ(errno, ERANGE); + EXPECT_EQ(str_end - long_number_range_test, 50l); + + const char *long_long_max_number_with_numbers_after = + "9223372036854775807123"; + errno = 0; + ASSERT_EQ(__llvm_libc::strtoll(long_long_max_number_with_numbers_after, + &str_end, 10), + LLONG_MAX); + ASSERT_EQ(errno, ERANGE); + EXPECT_EQ(str_end - long_long_max_number_with_numbers_after, 22l); } TEST(LlvmLibcStrToLLTest, MessyBaseTenDecode) { @@ -145,7 +176,7 @@ TEST(LlvmLibcStrToLLTest, DecodeInOtherBases) { char small_string[4] = {'\0', '\0', '\0', '\0'}; - for (int base = 2; base <= 36; ++base) { + for (unsigned int base = 2; base <= 36; ++base) { for (long long first_digit = 0; first_digit <= 36; ++first_digit) { small_string[0] = int_to_b36_char(first_digit); if (first_digit < base) { @@ -161,7 +192,7 @@ } } - for (int base = 2; base <= 36; ++base) { + for (unsigned int base = 2; base <= 36; ++base) { for (long long first_digit = 0; first_digit <= 36; ++first_digit) { small_string[0] = int_to_b36_char(first_digit); for (long long second_digit = 0; second_digit <= 36; ++second_digit) { @@ -185,7 +216,7 @@ } } - for (int base = 2; base <= 36; ++base) { + for (unsigned int base = 2; base <= 36; ++base) { for (long long first_digit = 0; first_digit <= 36; ++first_digit) { small_string[0] = int_to_b36_char(first_digit); for (long long second_digit = 0; second_digit <= 36; ++second_digit) { diff --git a/libc/test/src/stdlib/strtoll_test.cpp b/libc/test/src/stdlib/strtoul_test.cpp copy from libc/test/src/stdlib/strtoll_test.cpp copy to libc/test/src/stdlib/strtoul_test.cpp --- a/libc/test/src/stdlib/strtoll_test.cpp +++ b/libc/test/src/stdlib/strtoul_test.cpp @@ -1,4 +1,4 @@ -//===-- Unittests for strtoll ---------------------------------------------===// +//===-- Unittests for strtoul ---------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,131 +6,132 @@ // //===----------------------------------------------------------------------===// -#include "src/stdlib/strtoll.h" +#include "src/stdlib/strtoul.h" #include "utils/UnitTest/Test.h" #include #include -TEST(LlvmLibcStrToLLTest, InvalidBase) { +TEST(LlvmLibcStrToULTest, InvalidBase) { const char *ten = "10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(ten, nullptr, -1), 0ll); + ASSERT_EQ(__llvm_libc::strtoul(ten, nullptr, -1), 0ul); ASSERT_EQ(errno, EINVAL); } -TEST(LlvmLibcStrToLLTest, CleanBaseTenDecode) { +TEST(LlvmLibcStrToULTest, CleanBaseTenDecode) { char *str_end = nullptr; const char *ten = "10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(ten, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoul(ten, &str_end, 10), 10ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - ten, 2l); errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(ten, nullptr, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoul(ten, nullptr, 10), 10ul); ASSERT_EQ(errno, 0); const char *hundred = "100"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(hundred, &str_end, 10), 100ll); + ASSERT_EQ(__llvm_libc::strtoul(hundred, &str_end, 10), 100ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - hundred, 3l); const char *negative = "-100"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(negative, &str_end, 10), -100ll); + ASSERT_EQ(__llvm_libc::strtoul(negative, &str_end, 10), -(100ul)); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - negative, 4l); const char *big_number = "123456789012345"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(big_number, &str_end, 10), 123456789012345ll); + ASSERT_EQ(__llvm_libc::strtoul(big_number, &str_end, 10), 123456789012345ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - big_number, 15l); - const char *big_negative_number = "-123456789012345"; - errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(big_negative_number, &str_end, 10), - -123456789012345ll); - ASSERT_EQ(errno, 0); - EXPECT_EQ(str_end - big_negative_number, 16l); - const char *too_big_number = "123456789012345678901"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(too_big_number, &str_end, 10), LLONG_MAX); + ASSERT_EQ(__llvm_libc::strtoul(too_big_number, &str_end, 10), ULONG_MAX); ASSERT_EQ(errno, ERANGE); - EXPECT_EQ(str_end - too_big_number, 19l); + EXPECT_EQ(str_end - too_big_number, 21l); const char *too_big_negative_number = "-123456789012345678901"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(too_big_negative_number, &str_end, 10), - LLONG_MIN); + ASSERT_EQ(__llvm_libc::strtoul(too_big_negative_number, &str_end, 10), + ULONG_MAX); + ASSERT_EQ(errno, ERANGE); + EXPECT_EQ(str_end - too_big_negative_number, 22l); + + const char *long_number_range_test = + "10000000000000000000000000000000000000000000000000"; + errno = 0; + ASSERT_EQ(__llvm_libc::strtoul(long_number_range_test, &str_end, 10), + ULONG_MAX); ASSERT_EQ(errno, ERANGE); - EXPECT_EQ(str_end - too_big_negative_number, 20l); + EXPECT_EQ(str_end - long_number_range_test, 50l); } -TEST(LlvmLibcStrToLLTest, MessyBaseTenDecode) { +TEST(LlvmLibcStrToULTest, MessyBaseTenDecode) { char *str_end = nullptr; const char *spaces_before = " 10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(spaces_before, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoul(spaces_before, &str_end, 10), 10ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - spaces_before, 7l); const char *spaces_after = "10 "; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(spaces_after, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoul(spaces_after, &str_end, 10), 10ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - spaces_after, 2l); const char *word_before = "word10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(word_before, &str_end, 10), 0ll); + ASSERT_EQ(__llvm_libc::strtoul(word_before, &str_end, 10), 0ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - word_before, 0l); const char *word_after = "10word"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(word_after, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoul(word_after, &str_end, 10), 10ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - word_after, 2l); const char *two_numbers = "10 999"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(two_numbers, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoul(two_numbers, &str_end, 10), 10ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - two_numbers, 2l); const char *two_signs = "--10 999"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(two_signs, &str_end, 10), 0ll); + ASSERT_EQ(__llvm_libc::strtoul(two_signs, &str_end, 10), 0ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - two_signs, 1l); const char *sign_before = "+2=4"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(sign_before, &str_end, 10), 2ll); + ASSERT_EQ(__llvm_libc::strtoul(sign_before, &str_end, 10), 2ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - sign_before, 2l); const char *sign_after = "2+2=4"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(sign_after, &str_end, 10), 2ll); + ASSERT_EQ(__llvm_libc::strtoul(sign_after, &str_end, 10), 2ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - sign_after, 1l); const char *tab_before = "\t10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(tab_before, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoul(tab_before, &str_end, 10), 10ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - tab_before, 3l); const char *all_together = "\t -12345and+67890"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(all_together, &str_end, 10), -12345ll); + ASSERT_EQ(__llvm_libc::strtoul(all_together, &str_end, 10), -(12345ul)); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - all_together, 9l); } @@ -143,65 +144,65 @@ return 'A' + input - 10; } -TEST(LlvmLibcStrToLLTest, DecodeInOtherBases) { +TEST(LlvmLibcStrToULTest, DecodeInOtherBases) { char small_string[4] = {'\0', '\0', '\0', '\0'}; - for (int base = 2; base <= 36; ++base) { - for (long long first_digit = 0; first_digit <= 36; ++first_digit) { + for (unsigned int base = 2; base <= 36; ++base) { + for (unsigned long first_digit = 0; first_digit <= 36; ++first_digit) { small_string[0] = int_to_b36_char(first_digit); if (first_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), first_digit); ASSERT_EQ(errno, 0); } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), 0ll); + ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 0ul); ASSERT_EQ(errno, 0); } } } - for (int base = 2; base <= 36; ++base) { - for (long long first_digit = 0; first_digit <= 36; ++first_digit) { + for (unsigned int base = 2; base <= 36; ++base) { + for (unsigned long first_digit = 0; first_digit <= 36; ++first_digit) { small_string[0] = int_to_b36_char(first_digit); - for (long long second_digit = 0; second_digit <= 36; ++second_digit) { + for (unsigned long second_digit = 0; second_digit <= 36; ++second_digit) { small_string[1] = int_to_b36_char(second_digit); if (first_digit < base && second_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), second_digit + (first_digit * base)); ASSERT_EQ(errno, 0); } else if (first_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), first_digit); ASSERT_EQ(errno, 0); } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), 0ll); + ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 0ul); ASSERT_EQ(errno, 0); } } } } - for (int base = 2; base <= 36; ++base) { - for (long long first_digit = 0; first_digit <= 36; ++first_digit) { + for (unsigned int base = 2; base <= 36; ++base) { + for (unsigned long first_digit = 0; first_digit <= 36; ++first_digit) { small_string[0] = int_to_b36_char(first_digit); - for (long long second_digit = 0; second_digit <= 36; ++second_digit) { + for (unsigned long second_digit = 0; second_digit <= 36; ++second_digit) { small_string[1] = int_to_b36_char(second_digit); - for (long long third_digit = 0; third_digit <= 36; ++third_digit) { + for (unsigned long third_digit = 0; third_digit <= 36; ++third_digit) { small_string[2] = int_to_b36_char(third_digit); if (first_digit < base && second_digit < base && third_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), third_digit + (second_digit * base) + (first_digit * base * base)); ASSERT_EQ(errno, 0); } else if (first_digit < base && second_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), second_digit + (first_digit * base)); ASSERT_EQ(errno, 0); } else if (first_digit < base) { @@ -210,24 +211,24 @@ if (base == 16 && first_digit == 0 && second_digit == 33) { if (third_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), third_digit); ASSERT_EQ(errno, 0); } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), - 0ll); + ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), + 0ul); ASSERT_EQ(errno, 0); } } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), first_digit); ASSERT_EQ(errno, 0); } } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), 0ll); + ASSERT_EQ(__llvm_libc::strtoul(small_string, nullptr, base), 0ul); ASSERT_EQ(errno, 0); } } @@ -236,48 +237,48 @@ } } -TEST(LlvmLibcStrToLLTest, CleanBaseSixteenDecode) { +TEST(LlvmLibcStrToULTest, CleanBaseSixteenDecode) { char *str_end = nullptr; const char *no_prefix = "123abc"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(no_prefix, &str_end, 16), 0x123abcll); + ASSERT_EQ(__llvm_libc::strtoul(no_prefix, &str_end, 16), 0x123abcul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - no_prefix, 6l); const char *yes_prefix = "0x456def"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(yes_prefix, &str_end, 16), 0x456defll); + ASSERT_EQ(__llvm_libc::strtoul(yes_prefix, &str_end, 16), 0x456deful); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - yes_prefix, 8l); } -TEST(LlvmLibcStrToLLTest, AutomaticBaseSelection) { +TEST(LlvmLibcStrToULTest, AutomaticBaseSelection) { char *str_end = nullptr; const char *base_ten = "12345"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(base_ten, &str_end, 0), 12345ll); + ASSERT_EQ(__llvm_libc::strtoul(base_ten, &str_end, 0), 12345ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - base_ten, 5l); const char *base_sixteen_no_prefix = "123abc"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(base_sixteen_no_prefix, &str_end, 0), 123ll); + ASSERT_EQ(__llvm_libc::strtoul(base_sixteen_no_prefix, &str_end, 0), 123ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - base_sixteen_no_prefix, 3l); const char *base_sixteen_with_prefix = "0x456def"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(base_sixteen_with_prefix, &str_end, 0), - 0x456defll); + ASSERT_EQ(__llvm_libc::strtoul(base_sixteen_with_prefix, &str_end, 0), + 0x456deful); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - base_sixteen_with_prefix, 8l); const char *base_eight_with_prefix = "012345"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(base_eight_with_prefix, &str_end, 0), - 012345ll); + ASSERT_EQ(__llvm_libc::strtoul(base_eight_with_prefix, &str_end, 0), + 012345ul); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - base_eight_with_prefix, 6l); } diff --git a/libc/test/src/stdlib/strtoll_test.cpp b/libc/test/src/stdlib/strtoull_test.cpp copy from libc/test/src/stdlib/strtoll_test.cpp copy to libc/test/src/stdlib/strtoull_test.cpp --- a/libc/test/src/stdlib/strtoll_test.cpp +++ b/libc/test/src/stdlib/strtoull_test.cpp @@ -1,4 +1,4 @@ -//===-- Unittests for strtoll ---------------------------------------------===// +//===-- Unittests for strtoull --------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,131 +6,140 @@ // //===----------------------------------------------------------------------===// -#include "src/stdlib/strtoll.h" +#include "src/stdlib/strtoull.h" #include "utils/UnitTest/Test.h" #include #include -TEST(LlvmLibcStrToLLTest, InvalidBase) { +TEST(LlvmLibcStrToULLTest, InvalidBase) { const char *ten = "10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(ten, nullptr, -1), 0ll); + ASSERT_EQ(__llvm_libc::strtoull(ten, nullptr, -1), 0ull); ASSERT_EQ(errno, EINVAL); } -TEST(LlvmLibcStrToLLTest, CleanBaseTenDecode) { +TEST(LlvmLibcStrToULLTest, CleanBaseTenDecode) { char *str_end = nullptr; const char *ten = "10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(ten, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoull(ten, &str_end, 10), 10ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - ten, 2l); errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(ten, nullptr, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoull(ten, nullptr, 10), 10ull); ASSERT_EQ(errno, 0); const char *hundred = "100"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(hundred, &str_end, 10), 100ll); + ASSERT_EQ(__llvm_libc::strtoull(hundred, &str_end, 10), 100ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - hundred, 3l); const char *negative = "-100"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(negative, &str_end, 10), -100ll); + ASSERT_EQ(__llvm_libc::strtoull(negative, &str_end, 10), -(100ull)); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - negative, 4l); const char *big_number = "123456789012345"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(big_number, &str_end, 10), 123456789012345ll); + ASSERT_EQ(__llvm_libc::strtoull(big_number, &str_end, 10), + 123456789012345ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - big_number, 15l); - const char *big_negative_number = "-123456789012345"; + const char *unsigned_long_long_max_number = "18446744073709551615"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(big_negative_number, &str_end, 10), - -123456789012345ll); + ASSERT_EQ(__llvm_libc::strtoull(unsigned_long_long_max_number, &str_end, 10), + 18446744073709551615ull); ASSERT_EQ(errno, 0); - EXPECT_EQ(str_end - big_negative_number, 16l); + EXPECT_EQ(str_end - unsigned_long_long_max_number, 20l); const char *too_big_number = "123456789012345678901"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(too_big_number, &str_end, 10), LLONG_MAX); + ASSERT_EQ(__llvm_libc::strtoull(too_big_number, &str_end, 10), ULLONG_MAX); ASSERT_EQ(errno, ERANGE); - EXPECT_EQ(str_end - too_big_number, 19l); + EXPECT_EQ(str_end - too_big_number, 21l); const char *too_big_negative_number = "-123456789012345678901"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(too_big_negative_number, &str_end, 10), - LLONG_MIN); + ASSERT_EQ(__llvm_libc::strtoull(too_big_negative_number, &str_end, 10), + ULLONG_MAX); ASSERT_EQ(errno, ERANGE); - EXPECT_EQ(str_end - too_big_negative_number, 20l); + EXPECT_EQ(str_end - too_big_negative_number, 22l); + + const char *long_number_range_test = + "10000000000000000000000000000000000000000000000000"; + errno = 0; + ASSERT_EQ(__llvm_libc::strtoull(long_number_range_test, &str_end, 10), + ULLONG_MAX); + ASSERT_EQ(errno, ERANGE); + EXPECT_EQ(str_end - long_number_range_test, 50l); } -TEST(LlvmLibcStrToLLTest, MessyBaseTenDecode) { +TEST(LlvmLibcStrToULLTest, MessyBaseTenDecode) { char *str_end = nullptr; const char *spaces_before = " 10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(spaces_before, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoull(spaces_before, &str_end, 10), 10ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - spaces_before, 7l); const char *spaces_after = "10 "; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(spaces_after, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoull(spaces_after, &str_end, 10), 10ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - spaces_after, 2l); const char *word_before = "word10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(word_before, &str_end, 10), 0ll); + ASSERT_EQ(__llvm_libc::strtoull(word_before, &str_end, 10), 0ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - word_before, 0l); const char *word_after = "10word"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(word_after, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoull(word_after, &str_end, 10), 10ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - word_after, 2l); const char *two_numbers = "10 999"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(two_numbers, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoull(two_numbers, &str_end, 10), 10ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - two_numbers, 2l); const char *two_signs = "--10 999"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(two_signs, &str_end, 10), 0ll); + ASSERT_EQ(__llvm_libc::strtoull(two_signs, &str_end, 10), 0ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - two_signs, 1l); const char *sign_before = "+2=4"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(sign_before, &str_end, 10), 2ll); + ASSERT_EQ(__llvm_libc::strtoull(sign_before, &str_end, 10), 2ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - sign_before, 2l); const char *sign_after = "2+2=4"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(sign_after, &str_end, 10), 2ll); + ASSERT_EQ(__llvm_libc::strtoull(sign_after, &str_end, 10), 2ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - sign_after, 1l); const char *tab_before = "\t10"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(tab_before, &str_end, 10), 10ll); + ASSERT_EQ(__llvm_libc::strtoull(tab_before, &str_end, 10), 10ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - tab_before, 3l); const char *all_together = "\t -12345and+67890"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(all_together, &str_end, 10), -12345ll); + ASSERT_EQ(__llvm_libc::strtoull(all_together, &str_end, 10), -(12345ull)); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - all_together, 9l); } @@ -143,65 +152,68 @@ return 'A' + input - 10; } -TEST(LlvmLibcStrToLLTest, DecodeInOtherBases) { +TEST(LlvmLibcStrToULLTest, DecodeInOtherBases) { char small_string[4] = {'\0', '\0', '\0', '\0'}; - for (int base = 2; base <= 36; ++base) { - for (long long first_digit = 0; first_digit <= 36; ++first_digit) { + for (unsigned int base = 2; base <= 36; ++base) { + for (unsigned long long first_digit = 0; first_digit <= 36; ++first_digit) { small_string[0] = int_to_b36_char(first_digit); if (first_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), first_digit); ASSERT_EQ(errno, 0); } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), 0ll); + ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), 0ull); ASSERT_EQ(errno, 0); } } } - for (int base = 2; base <= 36; ++base) { - for (long long first_digit = 0; first_digit <= 36; ++first_digit) { + for (unsigned int base = 2; base <= 36; ++base) { + for (unsigned long long first_digit = 0; first_digit <= 36; ++first_digit) { small_string[0] = int_to_b36_char(first_digit); - for (long long second_digit = 0; second_digit <= 36; ++second_digit) { + for (unsigned long long second_digit = 0; second_digit <= 36; + ++second_digit) { small_string[1] = int_to_b36_char(second_digit); if (first_digit < base && second_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), second_digit + (first_digit * base)); ASSERT_EQ(errno, 0); } else if (first_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), first_digit); ASSERT_EQ(errno, 0); } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), 0ll); + ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), 0ull); ASSERT_EQ(errno, 0); } } } } - for (int base = 2; base <= 36; ++base) { - for (long long first_digit = 0; first_digit <= 36; ++first_digit) { + for (unsigned int base = 2; base <= 36; ++base) { + for (unsigned long long first_digit = 0; first_digit <= 36; ++first_digit) { small_string[0] = int_to_b36_char(first_digit); - for (long long second_digit = 0; second_digit <= 36; ++second_digit) { + for (unsigned long long second_digit = 0; second_digit <= 36; + ++second_digit) { small_string[1] = int_to_b36_char(second_digit); - for (long long third_digit = 0; third_digit <= 36; ++third_digit) { + for (unsigned long long third_digit = 0; third_digit <= 36; + ++third_digit) { small_string[2] = int_to_b36_char(third_digit); if (first_digit < base && second_digit < base && third_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), third_digit + (second_digit * base) + (first_digit * base * base)); ASSERT_EQ(errno, 0); } else if (first_digit < base && second_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), second_digit + (first_digit * base)); ASSERT_EQ(errno, 0); } else if (first_digit < base) { @@ -210,24 +222,24 @@ if (base == 16 && first_digit == 0 && second_digit == 33) { if (third_digit < base) { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), third_digit); ASSERT_EQ(errno, 0); } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), - 0ll); + ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), + 0ull); ASSERT_EQ(errno, 0); } } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), + ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), first_digit); ASSERT_EQ(errno, 0); } } else { errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(small_string, nullptr, base), 0ll); + ASSERT_EQ(__llvm_libc::strtoull(small_string, nullptr, base), 0ull); ASSERT_EQ(errno, 0); } } @@ -236,48 +248,48 @@ } } -TEST(LlvmLibcStrToLLTest, CleanBaseSixteenDecode) { +TEST(LlvmLibcStrToULLTest, CleanBaseSixteenDecode) { char *str_end = nullptr; const char *no_prefix = "123abc"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(no_prefix, &str_end, 16), 0x123abcll); + ASSERT_EQ(__llvm_libc::strtoull(no_prefix, &str_end, 16), 0x123abcull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - no_prefix, 6l); const char *yes_prefix = "0x456def"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(yes_prefix, &str_end, 16), 0x456defll); + ASSERT_EQ(__llvm_libc::strtoull(yes_prefix, &str_end, 16), 0x456defull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - yes_prefix, 8l); } -TEST(LlvmLibcStrToLLTest, AutomaticBaseSelection) { +TEST(LlvmLibcStrToULLTest, AutomaticBaseSelection) { char *str_end = nullptr; const char *base_ten = "12345"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(base_ten, &str_end, 0), 12345ll); + ASSERT_EQ(__llvm_libc::strtoull(base_ten, &str_end, 0), 12345ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - base_ten, 5l); const char *base_sixteen_no_prefix = "123abc"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(base_sixteen_no_prefix, &str_end, 0), 123ll); + ASSERT_EQ(__llvm_libc::strtoull(base_sixteen_no_prefix, &str_end, 0), 123ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - base_sixteen_no_prefix, 3l); const char *base_sixteen_with_prefix = "0x456def"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(base_sixteen_with_prefix, &str_end, 0), - 0x456defll); + ASSERT_EQ(__llvm_libc::strtoull(base_sixteen_with_prefix, &str_end, 0), + 0x456defull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - base_sixteen_with_prefix, 8l); const char *base_eight_with_prefix = "012345"; errno = 0; - ASSERT_EQ(__llvm_libc::strtoll(base_eight_with_prefix, &str_end, 0), - 012345ll); + ASSERT_EQ(__llvm_libc::strtoull(base_eight_with_prefix, &str_end, 0), + 012345ull); ASSERT_EQ(errno, 0); EXPECT_EQ(str_end - base_eight_with_prefix, 6l); }