[libc++] std::abs should not return double

Implement LWG Issue 2735 by adding std::abs
tests for several types and checking their
return value. NFC.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@369394 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/std/numerics/c.math/abs.fail.cpp b/test/std/numerics/c.math/abs.fail.cpp
new file mode 100644
index 0000000..5b7c77d
--- /dev/null
+++ b/test/std/numerics/c.math/abs.fail.cpp
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <cmath>
+
+#include "test_macros.h"
+
+int main(int, char**)
+{
+    unsigned int ui = -5;
+    ui = std::abs(ui); // expected-error {{call to 'abs' is ambiguous}}
+
+    unsigned char uc = -5;
+    uc = std::abs(uc); // expected-error {{taking the absolute value of unsigned type 'unsigned char' has no effect}}
+
+    unsigned short us = -5;
+    us = std::abs(us); // expected-error {{taking the absolute value of unsigned type 'unsigned short' has no effect}}
+
+    unsigned long ul = -5;
+    ul = std::abs(ul); // expected-error {{call to 'abs' is ambiguous}}
+
+    unsigned long long ull = -5;
+    ull = ::abs(ull); // expected-error {{call to 'abs' is ambiguous}}
+
+    return 0;
+}
+
diff --git a/test/std/numerics/c.math/abs.pass.cpp b/test/std/numerics/c.math/abs.pass.cpp
new file mode 100644
index 0000000..f0e4c57
--- /dev/null
+++ b/test/std/numerics/c.math/abs.pass.cpp
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <assert.h>
+#include <cmath>
+#include <cstdint>
+#include <type_traits>
+
+#include "test_macros.h"
+
+template<class T>
+struct correct_size_int
+{
+    typedef typename std::conditional<sizeof(T) <= sizeof(int), int, T>::type type;
+};
+
+template <class Source, class Result>
+void test_abs()
+{
+    Source neg_val = -5;
+    Source pos_val = 5;
+    Result res = 5;
+
+    ASSERT_SAME_TYPE(decltype(std::abs(neg_val)), Result);
+
+    assert(std::abs(neg_val) == res);
+    assert(std::abs(pos_val) == res);
+}
+
+void test_big()
+{
+    long long int big_value = std::numeric_limits<long long int>::max(); // a value to big for ints to store
+    long long int negative_big_value = -big_value;
+    assert(std::abs(negative_big_value) == big_value); // make sure it doesnt get casted to a smaller type
+}
+
+int main(int, char**)
+{
+    test_abs<short int, typename correct_size_int<short int>::type>();
+    test_abs<char, typename correct_size_int<char>::type>();
+    test_abs<signed char, typename correct_size_int<signed char>::type>();
+
+    test_abs<int, typename correct_size_int<int>::type>();
+    test_abs<long int, typename correct_size_int<long int>::type>();
+    test_abs<long long int, typename correct_size_int<long long int>::type>();
+
+    test_abs<std::int8_t, typename correct_size_int<std::int8_t>::type>();
+    test_abs<std::int16_t, typename correct_size_int<std::int16_t>::type>();
+    test_abs<std::int32_t, typename correct_size_int<std::int32_t>::type>();
+    test_abs<std::int64_t, typename correct_size_int<std::int64_t>::type>();
+
+    test_abs<long double, long double>();
+    test_abs<double, double>();
+    test_abs<float, float>();
+
+    test_big();
+
+    return 0;
+}
+
diff --git a/www/cxx1z_status.html b/www/cxx1z_status.html
index 100d159..d9b5562 100644
--- a/www/cxx1z_status.html
+++ b/www/cxx1z_status.html
@@ -415,7 +415,7 @@
 	<tr><td><a href="https://wg21.link/LWG2729">2729</a></td><td>Missing SFINAE on std::pair::operator=</td><td>Issaquah</td><td></td></tr>
 	<tr><td><a href="https://wg21.link/LWG2732">2732</a></td><td>Questionable specification of path::operator/= and path::append</td><td>Issaquah</td><td>Complete</td></tr>
 	<tr><td><a href="https://wg21.link/LWG2733">2733</a></td><td>[fund.ts.v2] gcd / lcm and bool</td><td>Issaquah</td><td>Complete</td></tr>
-	<tr><td><a href="https://wg21.link/LWG2735">2735</a></td><td>std::abs(short), std::abs(signed char) and others should return int instead of double in order to be compatible with C++98 and C</td><td>Issaquah</td><td></td></tr>
+	<tr><td><a href="https://wg21.link/LWG2735">2735</a></td><td>std::abs(short), std::abs(signed char) and others should return int instead of double in order to be compatible with C++98 and C</td><td>Issaquah</td><td>Complete</td></tr>
 	<tr><td><a href="https://wg21.link/LWG2736">2736</a></td><td>nullopt_t insufficiently constrained</td><td>Issaquah</td><td>Complete</td></tr>
 	<tr><td><a href="https://wg21.link/LWG2738">2738</a></td><td>is_constructible with void types</td><td>Issaquah</td><td>Complete</td></tr>
 	<tr><td><a href="https://wg21.link/LWG2739">2739</a></td><td>Issue with time_point non-member subtraction with an unsigned duration</td><td>Issaquah</td><td>Complete</td></tr>