Index: include/math.h =================================================================== --- include/math.h +++ include/math.h @@ -766,6 +766,14 @@ inline _LIBCPP_INLINE_VISIBILITY long double abs(long double __lcpp_x) _NOEXCEPT {return ::fabsl(__lcpp_x);} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename std::enable_if< + std::is_integral<_A1>::value && + !std::is_unsigned<_A1>::value, // allows for long long int, long int, int +_A1>::type +abs(_A1 __lcpp_x) _NOEXCEPT {return abs(__lcpp_x);} #endif // !(defined(_AIX) || defined(__sun__)) // acos Index: test/libcxx/numerics/c.math/abs.fail.cpp =================================================================== --- /dev/null +++ test/libcxx/numerics/c.math/abs.fail.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#include "test_macros.h" + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ + unsigned int ui = -5; + std::abs(ui); // unsigned types are not allowed + + long long double lld = -10; + std::abs(lld); // no overload and not `is_integral` + + return 0; +} + Index: test/libcxx/numerics/c.math/abs.pass.cpp =================================================================== --- /dev/null +++ test/libcxx/numerics/c.math/abs.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include + +#include "test_macros.h" + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +template +void test_abs() +{ + T val = -5; + T pos_val = 5; + + assert(abs(val) == 5); + assert(abs(pos_val) == 5); + + ASSERT_SAME_TYPE(decltype(abs(val)), T); +} + +void test_big() +{ + long long int big_value = 9223372036854775800; // a value to big for ints to store + long long int negative_big_value = -big_value; + assert(abs(negative_big_value) == big_value); // make sure it doesnt get casted to a smaller type +} + +int main() +{ + test_abs(); + test_abs(); + test_abs(); + test_abs(); + test_abs(); + test_abs(); + test_abs(); + test_abs(); + + test_big(); + + return 0; +} +