Skip to content

Commit c9f6d82

Browse files
committed
Use _LIBCPP_PREFERRED_OVERLOAD only for glibc + cxx03 and bionic
1 parent 4d4dadf commit c9f6d82

File tree

1 file changed

+48
-10
lines changed

1 file changed

+48
-10
lines changed

libcxx/include/__math/traits.h

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)