-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++] Fix acceptance of convertible-to-{float,double,long double} in std::isfinite() #98841
Conversation
The following error is raised if convertibles are used as arguments to isfinite(): "error: "no matching function for call to 'isfinite'".
This time, we test for the overload long double.
@llvm/pr-subscribers-libcxx Author: Robin Caloudis (robincaloudis) ChangesCloses #98816. Full diff: https://github.com/llvm/llvm-project/pull/98841.diff 2 Files Affected:
diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index a448266797557..07e5a74ac2362 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -55,6 +55,20 @@ _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfin
return true;
}
+#ifdef _LIBCPP_PREFERRED_OVERLOAD
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(float __x) _NOEXCEPT {
+ return __builtin_isfinite(__x);
+}
+
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool
+isfinite(double __x) _NOEXCEPT {
+ return __builtin_isfinite(__x);
+}
+
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(long double __x) _NOEXCEPT {
+ return __builtin_isfinite(__x);
+}
+#endif
// isinf
template <class _A1, __enable_if_t<is_arithmetic<_A1>::value && numeric_limits<_A1>::has_infinity, int> = 0>
diff --git a/libcxx/test/std/numerics/c.math/isfinite.pass.cpp b/libcxx/test/std/numerics/c.math/isfinite.pass.cpp
index 6bbc3aaac6d13..56d9550348a9b 100644
--- a/libcxx/test/std/numerics/c.math/isfinite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isfinite.pass.cpp
@@ -62,9 +62,42 @@ struct TestInt {
}
};
+struct ConvertibleFloat {
+ int value;
+
+ ConvertibleFloat(int v) : value(v) {}
+
+ operator float() const {
+ return static_cast<float>(value);
+ }
+};
+
+struct ConvertibleDouble {
+ int value;
+
+ ConvertibleDouble(int v) : value(v) {}
+
+ operator double() const {
+ return static_cast<double>(value);
+ }
+};
+
+struct ConvertibleLongDouble {
+ int value;
+
+ ConvertibleLongDouble(int v) : value(v) {}
+
+ operator long double() const {
+ return static_cast<long double>(value);
+ }
+};
+
int main(int, char**) {
types::for_each(types::floating_point_types(), TestFloat());
types::for_each(types::integral_types(), TestInt());
+ assert(std::isfinite(ConvertibleFloat(0)));
+ assert(std::isfinite(ConvertibleDouble(0)));
+ assert(std::isfinite(ConvertibleLongDouble(0)));
return 0;
}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Fails in gcc test... Looks like std::isnan |
Thanks for the patch! Is there a reason why we must apply |
8d9bd88
to
276d412
Compare
276d412
to
c858bb6
Compare
Thanks for the hint! You two are completely right. Once this is merged, I will also properly test the convertible types for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also check the other traits to make sure they're correctly implemented?
Sure, I'll check them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM once CI is done running. MacOS is a bit backed up right now due to an outage but it should get there eventually. Thanks!
Sorry, @philnik777 and I got in a race condition. Please make sure to satisfy Nikolas' requests as well. Thanks :-) |
2e6a04d
to
8d56623
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be merged once CI is done running.
CI is done running. Could you merge this PR? I lack write access. Thanks! |
That was quick! Thanks everyone! |
…in std::isfinite() (llvm#98841) Closes llvm#98816.
…in std::isfinite() (llvm#98841) Closes llvm#98816.
…in std::isfinite() (#98841) Summary: Closes #98816. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60250840
…and `std::isinf()` (#98952) Following up on #98841. Changes: - Properly test convertible types for `std::isnan()` and `std::inf()` - Tighten conditional in `cmath.pass.cpp` (Find insights on `_LIBCPP_PREFERRED_OVERLOAD` below) - Tighten preprocessor guard in `traits.h` Insights into why `_LIBCPP_PREFERRED_OVERLOAD` is needed: (i) When libc++ is layered on top of glibc on Linux, glibc's `math.h` is included. When compiling with `-std=c++03`, this header brings the function declaration of `isinf(double)` [1] and `isnan(double)` [2] into scope. This differs from the C99 Standard as only the macros `#define isnan(arg)` and `#define isinf(arg)` are expected. Therefore, libc++ needs to respect the presense of the `double` overload and cannot redefine it as it will conflict with the declaration already in scope. For `-std=c++11` and beyond this issue is fixed, as glibc guards both the `isinf` and `isnan` by preprocessor macros. (ii) When libc++ is layered on top of Bionic's libc, `math.h` exposes a function prototype for `isinf(double)` with return type `int`. This function prototype in Bionic's libc is not guarded by any preprocessor macros [3]. `_LIBCPP_PREFERRED_OVERLOAD` specifies that a given overload is a better match than an otherwise equally good function declaration. This is implemented in modern versions of Clang via `__attribute__((__enable_if__))`, and not elsewhere. See [4] for details. We use `_LIBCPP_PREFERRED_OVERLOAD` to define overloads in the global namespace that displace the overloads provided by the C libraries mentioned above. [1]: https://github.com/bminor/glibc/blob/fe9408087583fd7a6f61bb0dbcf2fd4e83186afa/math/bits/mathcalls.h#L185-L194 [2]: https://github.com/bminor/glibc/blob/fe9408087583fd7a6f61bb0dbcf2fd4e83186afa/math/bits/mathcalls.h#L222-L231 [3]: https://cs.android.com/android/platform/superproject/+/master:bionic/libc/include/math.h;l=322-323;drc=master?hl=fr-BE%22https:%2F%2Fsupport.google.com%2Fmerchants%2Fanswer%2F188494%5C%22%22https:%2F%2Fsupport.google.com%2Fmerchants%2Fanswer%2F188494%5C%22 [4]: 5fd17ab
…sfinite}` (llvm#106224) ## Why Since llvm#98841 and llvm#98952, the constrained overloads are unused and not needed anymore as we added explicit overloads for all floating point types. I forgot to remove them in the mentioned PRs. ## What Remove them.
Closes #98816.