@@ -69,30 +69,49 @@ _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI boo
6969
7070// isinf
7171
72- template <class _A1 , __enable_if_t <is_arithmetic <_A1>::value && numeric_limits<_A1>::has_infinity , int > = 0 >
72+ template <class _A1 , __enable_if_t <is_floating_point <_A1>::value, int > = 0 >
7373_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf (_A1 __x) _NOEXCEPT {
7474 return __builtin_isinf ((typename __promote<_A1>::type)__x);
7575}
7676
77- template <class _A1 , __enable_if_t <is_arithmetic <_A1>::value && !numeric_limits<_A1>::has_infinity , int > = 0 >
77+ template <class _A1 , __enable_if_t <is_integral <_A1>::value, int > = 0 >
7878_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf (_A1) _NOEXCEPT {
7979 return false ;
8080}
8181
82- #ifdef _LIBCPP_PREFERRED_OVERLOAD
8382_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf (float __x) _NOEXCEPT {
8483 return __builtin_isinf (__x);
8584}
8685
87- _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool
88- isinf (double __x) _NOEXCEPT {
86+ _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
87+ // When libc++ is layered on top of glibc on Linux, glibc's `math.h` is included. When compiling with
88+ // `-std=c++03`, this header brings the function declaration of `isinf(double)` with return type of
89+ // `int` into scope. This differs from the C99 standard as only a macro of the form `#define isinf(arg)`
90+ // is expected. Therefore, libc++ needs to respect the presense of this `double` overload with return type
91+ // `int` and cannot redefine it with return type `bool` like it is supposed to be, as it will conflict with
92+ // the declaration already in scope. For `-std=c++11` and beyond this issue is fixed, as glibc guards the
93+ // `double` overload of `isinf` by preprocessor macros.
94+ //
95+ // When libc++ is layered on top of Bionic's libc, `math.h` exposes a function prototype for `isnan(double)`
96+ // with return type `int`. This function prototype in Bionic's libc is not guarded by any preprocessor macros
97+ // and will therefore conflict.
98+ //
99+ // `_LIBCPP_PREFERRED_OVERLOAD` specifies that a given overload is a better match than an otherwise equally good
100+ // function declaration. This is implemented in modern versions of Clang via `__attribute__((__enable_if__))`, and
101+ // not elsewhere. See https://github.com/llvm/llvm-project/commit/5fd17ab1b093f6b59aabb27f6c2c2278e65c2707 for
102+ // details. We use `_LIBCPP_PREFERRED_OVERLOAD` to define overloads in the global namespace that displace the
103+ // overloads provided by the C libraries mentioned above.
104+ #if ((defined(_LIBCPP_CXX03_LANG) && defined(__GLIBC__)) || defined(__BIONIC__)) && defined(_LIBCPP_PREFERRED_OVERLOAD)
105+ _LIBCPP_PREFERRED_OVERLOAD
106+ #endif
107+ bool
108+ isinf (double __x) _NOEXCEPT {
89109 return __builtin_isinf (__x);
90110}
91111
92112_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf (long double __x) _NOEXCEPT {
93113 return __builtin_isinf (__x);
94114}
95- #endif
96115
97116// isnan
98117
@@ -106,20 +125,39 @@ _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan
106125 return false ;
107126}
108127
109- #ifdef _LIBCPP_PREFERRED_OVERLOAD
110128_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan (float __x) _NOEXCEPT {
111129 return __builtin_isnan (__x);
112130}
113131
114- _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool
115- isnan (double __x) _NOEXCEPT {
132+ _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
133+ // When libc++ is layered on top of glibc on Linux, glibc's `math.h` is included. When compiling with
134+ // `-std=c++03`, this header brings the function declaration of `isnan(double)` with return type of
135+ // `int` into scope. This differs from the C99 standard as only a macro of the form `#define isnan(arg)`
136+ // is expected. Therefore, libc++ needs to respect the presense of this `double` overload with return type
137+ // `int` and cannot redefine it with return type `bool` like it is supposed to be, as it will conflict with
138+ // the declaration already in scope. For `-std=c++11` and beyond this issue is fixed, as glibc guards the
139+ // `double` overload of `isnan` by preprocessor macros.
140+ //
141+ // When libc++ is layered on top of Bionic's libc, `math.h` exposes a function prototype for `isnan(double)`
142+ // with return type `int`. This function prototype in Bionic's libc is not guarded by any preprocessor macros
143+ // and will therefore conflict.
144+ //
145+ // `_LIBCPP_PREFERRED_OVERLOAD` specifies that a given overload is a better match than an otherwise equally good
146+ // function declaration. This is implemented in modern versions of Clang via `__attribute__((__enable_if__))`, and
147+ // not elsewhere. See https://github.com/llvm/llvm-project/commit/5fd17ab1b093f6b59aabb27f6c2c2278e65c2707 for
148+ // details. We use `_LIBCPP_PREFERRED_OVERLOAD` to define overloads in the global namespace that displace the
149+ // overloads provided by the C libraries mentioned above.
150+ #if ((defined(_LIBCPP_CXX03_LANG) && defined(__GLIBC__)) || defined(__BIONIC__)) && defined(_LIBCPP_PREFERRED_OVERLOAD)
151+ _LIBCPP_PREFERRED_OVERLOAD
152+ #endif
153+ bool
154+ isnan (double __x) _NOEXCEPT {
116155 return __builtin_isnan (__x);
117156}
118157
119158_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan (long double __x) _NOEXCEPT {
120159 return __builtin_isnan (__x);
121160}
122- #endif
123161
124162// isnormal
125163
0 commit comments