diff --git a/libc/src/stdlib/atoi.cpp b/libc/src/stdlib/atoi.cpp --- a/libc/src/stdlib/atoi.cpp +++ b/libc/src/stdlib/atoi.cpp @@ -13,11 +13,13 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, atoi, (const char *str)) { - auto result = internal::strtointeger(str, 10); + // This is done because the standard specifies that atoi is identical to + // (int)(strtol). + auto result = internal::strtointeger(str, 10); if (result.has_error()) errno = result.error; - return result; + return static_cast(result); } } // namespace __llvm_libc diff --git a/libc/test/src/stdlib/AtoiTest.h b/libc/test/src/stdlib/AtoiTest.h --- a/libc/test/src/stdlib/AtoiTest.h +++ b/libc/test/src/stdlib/AtoiTest.h @@ -6,10 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "src/__support/CPP/type_traits.h" #include "utils/UnitTest/Test.h" #include +using __llvm_libc::cpp::is_same_v; + template struct AtoTest : public __llvm_libc::testing::Test { using FunctionT = ReturnT (*)(const char *); @@ -54,6 +57,26 @@ const char *smallest_long_long = "-9223372036854775808"; ASSERT_EQ(func(smallest_long_long), static_cast(LLONG_MIN)); } + + // If this is atoi and the size of int is less than the size of long, then + // we parse as long and cast to int to match existing behavior. This only + // matters for cases where the result would be outside of the int range, and + // those cases are undefined, so we can choose whatever output value we + // want. In this case we have chosen to cast since that matches existing + // implementations and makes differential fuzzing easier, but no user should + // rely on this behavior. + if constexpr (is_same_v && sizeof(ReturnT) < sizeof(long)) { + + static_assert(sizeof(int) == 4); + + const char *bigger_than_biggest_int = "2147483649"; + ASSERT_EQ(func(bigger_than_biggest_int), + static_cast(2147483649)); + + const char *smaller_than_smallest_int = "-2147483649"; + ASSERT_EQ(func(smaller_than_smallest_int), + static_cast(-2147483649)); + } } void nonBaseTenWholeNumbers(FunctionT func) {