Patch by Howard. First part of fix for PR18218; add type traits needed to do the right thing. Fix the problems in PR18218 for isnan and pow - they also need to be applied to the other functions in <cmath>. Also, a drive-by fix for the test - now actually calls test_abs()
llvm-svn: 198431
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: d41295da72e2f264699672c97aeaff55fff219a2
diff --git a/include/__config b/include/__config
index f992bd5..8aa57ac 100644
--- a/include/__config
+++ b/include/__config
@@ -326,9 +326,11 @@
#if (__has_feature(cxx_noexcept))
# define _NOEXCEPT noexcept
# define _NOEXCEPT_(x) noexcept(x)
+# define _NOEXCEPT_OR_FALSE(x) noexcept(x)
#else
# define _NOEXCEPT throw()
# define _NOEXCEPT_(x)
+# define _NOEXCEPT_OR_FALSE(x) false
#endif
#if __has_feature(underlying_type)
@@ -361,6 +363,7 @@
#define _NOEXCEPT throw()
#define _NOEXCEPT_(x)
+#define _NOEXCEPT_OR_FALSE(x) false
#ifndef __GXX_EXPERIMENTAL_CXX0X__
@@ -433,6 +436,7 @@
#define _NOEXCEPT throw()
#define _NOEXCEPT_(x)
+#define _NOEXCEPT_OR_FALSE(x) false
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {
#define _LIBCPP_END_NAMESPACE_STD }
@@ -451,6 +455,7 @@
#define _NOEXCEPT throw()
#define _NOEXCEPT_(x)
+#define _NOEXCEPT_OR_FALSE(x) false
#define _LIBCPP_HAS_NO_TEMPLATE_ALIASES
#define _LIBCPP_HAS_NO_ADVANCED_SFINAE
diff --git a/include/cmath b/include/cmath
index 75087ae..4f27978 100644
--- a/include/cmath
+++ b/include/cmath
@@ -419,12 +419,25 @@
#undef isnan
-template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
-typename std::enable_if<std::is_arithmetic<_A1>::value, bool>::type
-isnan(_A1 __x) _NOEXCEPT
+bool
+isnan(float __x) _NOEXCEPT
{
- return __libcpp_isnan((typename std::__promote<_A1>::type)__x);
+ return __libcpp_isnan(__x);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+bool
+isnan(double __x) _NOEXCEPT
+{
+ return __libcpp_isnan(__x);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+bool
+isnan(long double __x) _NOEXCEPT
+{
+ return __libcpp_isnan(__x);
}
#endif // isnan
@@ -652,6 +665,26 @@
using ::float_t;
using ::double_t;
+// isnan
+
+template <class _A1>
+inline _LIBCPP_INLINE_VISIBILITY
+typename std::enable_if<__promote<_A1>::value, bool>::type
+#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+isnan(_A1 __x)
+#else
+isnan(_A1&& __x)
+ _NOEXCEPT_
+ (
+ _NOEXCEPT_(__promote<_A1>::__does_not_throw)
+ )
+#endif
+{
+ typedef typename __promote<_A1>::type type;
+ static_assert(!(is_same<typename remove_reference<_A1>::type, type>::value), "");
+ return __libcpp_isnan(static_cast<type>(_VSTD::forward<_A1>(__x)));
+}
+
// abs
#if !defined(_AIX)
@@ -952,21 +985,27 @@
template <class _A1, class _A2>
inline _LIBCPP_INLINE_VISIBILITY
-typename enable_if
-<
- is_arithmetic<_A1>::value &&
- is_arithmetic<_A2>::value,
- typename __promote<_A1, _A2>::type
->::type
-pow(_A1 __x, _A2 __y) _NOEXCEPT
+typename __promote<_A1, _A2>::type
+#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+pow(_A1 __x, _A2 __y)
+#else
+pow(_A1&& __x, _A2&& __y)
+ _NOEXCEPT_
+ (
+ _NOEXCEPT_(__promote<_A1>::__does_not_throw) &&
+ _NOEXCEPT_(__promote<_A2>::__does_not_throw)
+ )
+#endif
{
- typedef typename __promote<_A1, _A2>::type __result_type;
- static_assert((!(is_same<_A1, __result_type>::value &&
- is_same<_A2, __result_type>::value)), "");
- return pow((__result_type)__x, (__result_type)__y);
+ typedef typename __promote<_A1>::type _D1;
+ typedef typename __promote<_A2>::type _D2;
+ typedef typename __promote<_D1, _D2>::type type;
+ static_assert((!(is_same<typename remove_reference<_A1>::type, type>::value &&
+ is_same<typename remove_reference<_A2>::type, type>::value)), "");
+ return pow(static_cast<type>(static_cast<_D1>(_VSTD::forward<_A1>(__x))),
+ static_cast<type>(static_cast<_D2>(_VSTD::forward<_A2>(__y))));
}
-
// sin
using ::sin;
diff --git a/include/type_traits b/include/type_traits
index 0ad7b7f..04e5fd1 100644
--- a/include/type_traits
+++ b/include/type_traits
@@ -1151,13 +1151,41 @@
#endif // _LIBCPP_HAS_NO_VARIADICS
+template <class _Tp>
+struct __numeric_type
+{
+ static void __test(...);
+ static float __test(float);
+ static double __test(char);
+ static double __test(int);
+ static double __test(unsigned);
+ static double __test(long);
+ static double __test(unsigned long);
+ static double __test(long long);
+ static double __test(unsigned long long);
+ static double __test(double);
+ static long double __test(long double);
+
+ typedef decltype(__test(declval<_Tp>())) type;
+ static const bool value = !is_same<type, void>::value;
+};
+
+template <>
+struct __numeric_type<void>
+{
+ static const bool value = true;
+};
+
// __promote
template <class _A1, class _A2 = void, class _A3 = void,
- bool = (is_arithmetic<_A1>::value || is_void<_A1>::value) &&
- (is_arithmetic<_A2>::value || is_void<_A2>::value) &&
- (is_arithmetic<_A3>::value || is_void<_A3>::value)>
-class __promote {};
+ bool = __numeric_type<_A1>::value &&
+ __numeric_type<_A2>::value &&
+ __numeric_type<_A3>::value>
+class __promote
+{
+ static const bool value = false;
+};
template <class _A1, class _A2, class _A3>
class __promote<_A1, _A2, _A3, true>
@@ -1168,6 +1196,7 @@
typedef typename __promote<_A3>::type __type3;
public:
typedef decltype(__type1() + __type2() + __type3()) type;
+ static const bool value = true;
};
template <class _A1, class _A2>
@@ -1178,16 +1207,16 @@
typedef typename __promote<_A2>::type __type2;
public:
typedef decltype(__type1() + __type2()) type;
+ static const bool value = true;
};
template <class _A1>
class __promote<_A1, void, void, true>
{
public:
- typedef typename conditional<is_arithmetic<_A1>::value,
- typename conditional<is_integral<_A1>::value, double, _A1>::type,
- void
- >::type type;
+ typedef typename __numeric_type<_A1>::type type;
+ static const bool value = true;
+ static const bool __does_not_throw = _NOEXCEPT_OR_FALSE(static_cast<type>(declval<_A1>()));
};
#ifdef _LIBCPP_STORE_AS_OPTIMIZATION