[libcxx-commits] [libcxx] [libc++][math] Provide overloads for cv-unqualified floating point types for `std::isnormal` (PR #104773)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Aug 22 13:16:48 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Robin Caloudis (robincaloudis)
<details>
<summary>Changes</summary>
## Why
Currently, the following does not work when compiled with clang:
```c++
#include <cmath>
struct ConvertibleToFloat {
operator float();
};
bool test(ConvertibleToFloat x) {
return std::isnormal(x);
}
```
See https://godbolt.org/z/5bos8v67T for differences with respect to msvc, gcc or icx. If fails for `double` and `long double` as well. As the classification/comparison function `isnormal` is defined since C++11 until C++23 as
```c++
bool isnormal( float num );
bool isnormal( double num );
bool isnormal( long double num );
```
and since C++23 as
```c++
constexpr bool isnormal( /* floating-point-type */ num );
```
for which "the library provides overloads for all cv-unqualified floating-point types as the type of the parameter num", it is actually expected that convertibles types work due to the present of the overloads for all cv-unqualified floating point types. See §28.7.1/1 in the [ISO C++ standard](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4950.pdf) or check [cppreference](https://en.cppreference.com/w/cpp/numeric/math/isnormal).
## What
Test and provide overloads as expected by the ISO C++ standard.
---
Full diff: https://github.com/llvm/llvm-project/pull/104773.diff
2 Files Affected:
- (modified) libcxx/include/__math/traits.h (+12)
- (modified) libcxx/test/std/numerics/c.math/isnormal.pass.cpp (+14)
``````````diff
diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index 35c283cc9e21ce..9fe1de66a80985 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -137,6 +137,18 @@ _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnor
return __x != 0;
}
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(float __x) _NOEXCEPT {
+ return __builtin_isnormal(__x);
+}
+
+_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
template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
diff --git a/libcxx/test/std/numerics/c.math/isnormal.pass.cpp b/libcxx/test/std/numerics/c.math/isnormal.pass.cpp
index c3b8f31359f988..76c3d13520d996 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 <typename T>
+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<float>()));
+ assert(std::isnormal(ConvertibleTo<double>()));
+ assert(std::isnormal(ConvertibleTo<long double>()));
+ }
+
return 0;
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/104773
More information about the libcxx-commits
mailing list