diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h index 35c283cc9e21c..2ca231e0428fb 100644 --- a/libcxx/include/__math/traits.h +++ b/libcxx/include/__math/traits.h @@ -127,14 +127,21 @@ _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI boo // isnormal -template ::value, int> = 0> +template ::value, int> = 0> _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { + return __x != 0; +} + +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(float __x) _NOEXCEPT { return __builtin_isnormal(__x); } -template ::value, int> = 0> -_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { - return __x != 0; +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(double __x) _NOEXCEPT { + return __builtin_isnormal(__x); +} + +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(long double __x) _NOEXCEPT { + return __builtin_isnormal(__x); } // isgreater diff --git a/libcxx/test/std/numerics/c.math/isnormal.pass.cpp b/libcxx/test/std/numerics/c.math/isnormal.pass.cpp index c3b8f31359f98..76c3d13520d99 100644 --- a/libcxx/test/std/numerics/c.math/isnormal.pass.cpp +++ b/libcxx/test/std/numerics/c.math/isnormal.pass.cpp @@ -62,9 +62,23 @@ struct TestInt { } }; +template +struct ConvertibleTo { + operator T() const { return T(1); } +}; + int main(int, char**) { types::for_each(types::floating_point_types(), TestFloat()); types::for_each(types::integral_types(), TestInt()); + // Make sure we can call `std::isnormal` with convertible types. This checks + // whether overloads for all cv-unqualified floating-point types are working + // as expected. + { + assert(std::isnormal(ConvertibleTo())); + assert(std::isnormal(ConvertibleTo())); + assert(std::isnormal(ConvertibleTo())); + } + return 0; }