namespace __llvm_libc {
LLVM_LIBC_FUNCTION(int, atoi, (const char *str)) {
- auto result = internal::strtointeger<int>(str, 10);
+ // This is done because the standard specifies that atoi is identical to
+ // (int)(strtol).
+ auto result = internal::strtointeger<long>(str, 10);
if (result.has_error())
errno = result.error;
- return result;
+ return static_cast<int>(result);
}
} // namespace __llvm_libc
//
//===----------------------------------------------------------------------===//
+#include "src/__support/CPP/type_traits.h"
#include "utils/UnitTest/Test.h"
#include <limits.h>
+using __llvm_libc::cpp::is_same_v;
+
template <typename ReturnT> struct AtoTest : public __llvm_libc::testing::Test {
using FunctionT = ReturnT (*)(const char *);
const char *smallest_long_long = "-9223372036854775808";
ASSERT_EQ(func(smallest_long_long), static_cast<ReturnT>(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<ReturnT, int> && 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<ReturnT>(2147483649));
+
+ const char *smaller_than_smallest_int = "-2147483649";
+ ASSERT_EQ(func(smaller_than_smallest_int),
+ static_cast<ReturnT>(-2147483649));
+ }
}
void nonBaseTenWholeNumbers(FunctionT func) {