From f54f52c472334eb7e9c555bf429bb9f75325a80b Mon Sep 17 00:00:00 2001 From: Robin Caloudis Date: Sat, 24 Aug 2024 18:00:25 +0200 Subject: [PATCH 01/10] Test constexpr for signbit() --- .../c.math/constexpr-cxx23-clang.pass.cpp | 6 +- .../c.math/constexpr-cxx23-gcc.pass.cpp | 6 +- .../test/std/numerics/c.math/signbit.pass.cpp | 131 ++++++++++++++++++ libcxx/test/support/type_algorithms.h | 20 ++- 4 files changed, 150 insertions(+), 13 deletions(-) create mode 100644 libcxx/test/std/numerics/c.math/signbit.pass.cpp diff --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp index a07260a34516f17..20887b8cf2678b3 100644 --- a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp +++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp @@ -220,9 +220,9 @@ int main(int, char**) { ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0) == 1); ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0L) == 1); - ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1); - ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1); - ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1); + ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1); + ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1); + ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1); ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0f, 0.0f) == 0); ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0); diff --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp index 8c481f41a945ed0..d8779706bcee223 100644 --- a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp +++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-gcc.pass.cpp @@ -217,9 +217,9 @@ int main(int, char**) { ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0) == 1); ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0L) == 1); - ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1); - ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1); - ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1); + ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1); + ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1); + ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1); ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0f, 0.0f) == 0); ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0); diff --git a/libcxx/test/std/numerics/c.math/signbit.pass.cpp b/libcxx/test/std/numerics/c.math/signbit.pass.cpp new file mode 100644 index 000000000000000..cdeab92e0836e27 --- /dev/null +++ b/libcxx/test/std/numerics/c.math/signbit.pass.cpp @@ -0,0 +1,131 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// bool signbit(floating-point-type x); // constexpr since C++23 + +// We don't control the implementation on windows +// UNSUPPORTED: windows + +#include +#include +#include + +#include "test_macros.h" +#include "type_algorithms.h" + +struct TestFloat { + template + static TEST_CONSTEXPR_CXX23 bool test() { + assert(!std::signbit(T(0))); + assert(!std::signbit(std::numeric_limits::min())); + assert(!std::signbit(std::numeric_limits::denorm_min())); + assert(!std::signbit(std::numeric_limits::max())); + assert(!std::signbit(std::numeric_limits::infinity())); + assert(!std::signbit(std::numeric_limits::quiet_NaN())); + assert(!std::signbit(std::numeric_limits::signaling_NaN())); + assert(std::signbit(-T(0))); + assert(std::signbit(-std::numeric_limits::infinity())); + assert(std::signbit(std::numeric_limits::lowest())); + + return true; + } + + template + TEST_CONSTEXPR_CXX23 void operator()() { + test(); +#if TEST_STD_VER >= 23 + static_assert(test()); +#endif + } +}; + +struct TestUnsignedIntAndFixedWidthChar { + template + static TEST_CONSTEXPR_CXX23 bool test() { + assert(!std::signbit(std::numeric_limits::max())); + assert(!std::signbit(T(0))); + assert(!std::signbit(std::numeric_limits::lowest())); + + return true; + } + + template + TEST_CONSTEXPR_CXX23 void operator()() { + test(); +#if TEST_STD_VER >= 23 + static_assert(test()); +#endif + } +}; + +struct TestSignedInt { + template + static TEST_CONSTEXPR_CXX23 bool test() { + assert(!std::signbit(std::numeric_limits::max())); + assert(!std::signbit(T(0))); + assert(std::signbit(std::numeric_limits::lowest())); + + return true; + } + + template + TEST_CONSTEXPR_CXX23 void operator()() { + test(); +#if TEST_STD_VER >= 23 + static_assert(test()); +#endif + } +}; + +struct TestVariableWidthChar { + template + static TEST_CONSTEXPR_CXX23 bool test() { + assert(!std::signbit(std::numeric_limits::max())); + assert(!std::signbit(T(0))); + // Signed or unsigned depending on the architecture and platform. + if (std::is_unsigned::value) { + assert(!std::signbit(std::numeric_limits::lowest())); + } else { + assert(std::signbit(std::numeric_limits::lowest())); + } + + return true; + } + + template + TEST_CONSTEXPR_CXX23 void operator()() { + test(); +#if TEST_STD_VER >= 23 + static_assert(test()); +#endif + } +}; + +template +struct ConvertibleTo { + operator T() const { return T(); } +}; + +int main(int, char**) { + types::for_each(types::floating_point_types(), TestFloat()); + types::for_each(types::concatenate_t(), + TestUnsignedIntAndFixedWidthChar()); + types::for_each(types::signed_integer_types(), TestSignedInt()); + types::for_each(types::variable_width_character_types(), TestVariableWidthChar()); + + // Make sure we can call `std::signbit` with convertible types. This checks + // whether overloads for all cv-unqualified floating-point types are working + // as expected. + { + assert(!std::signbit(ConvertibleTo())); + assert(!std::signbit(ConvertibleTo())); + assert(!std::signbit(ConvertibleTo())); + } + + return 0; +} diff --git a/libcxx/test/support/type_algorithms.h b/libcxx/test/support/type_algorithms.h index da3d0add4d0c457..6b3b9aba11e5ecd 100644 --- a/libcxx/test/support/type_algorithms.h +++ b/libcxx/test/support/type_algorithms.h @@ -82,22 +82,28 @@ struct partial_instantiation { // type categories defined in [basic.fundamental] plus extensions (without CV-qualifiers) -using character_types = +using variable_width_character_types = type_list; + +using fixed_width_character_types = type_list< #ifndef TEST_HAS_NO_CHAR8_T - , - char8_t + char8_t #endif #if TEST_STD_VER >= 11 - , - char16_t, - char32_t +# ifndef TEST_HAS_NO_CHAR8_T + , +# endif + char16_t, + char32_t #endif - >; + >; + +using character_types = concatenate_t; using signed_integer_types = type_list Date: Sat, 24 Aug 2024 18:00:56 +0200 Subject: [PATCH 02/10] Add constexpr for signbit() --- libcxx/include/__math/traits.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h index 0638a6949580ebd..9be06b7b8efae9c 100644 --- a/libcxx/include/__math/traits.h +++ b/libcxx/include/__math/traits.h @@ -28,17 +28,29 @@ namespace __math { // signbit template ::value, int> = 0> -_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { + return __builtin_signbit(__x); +} + +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(float __x) _NOEXCEPT { + return __builtin_signbit(__x); +} + +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(double __x) _NOEXCEPT { + return __builtin_signbit(__x); +} + +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(long double __x) _NOEXCEPT { return __builtin_signbit(__x); } template ::value && is_signed<_A1>::value, int> = 0> -_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __x < 0; } template ::value && !is_signed<_A1>::value, int> = 0> -_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { return false; } From a9e2291a0ae7e62e2adc0df9ed535ba0a4d73ca4 Mon Sep 17 00:00:00 2001 From: Robin Caloudis Date: Sat, 24 Aug 2024 18:01:43 +0200 Subject: [PATCH 03/10] Update cxx23 status --- libcxx/docs/Status/Cxx23Papers.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv index 2c8a91d8401b538..20bd7b70a0d6199 100644 --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -39,7 +39,7 @@ "`P2401R0 `__","Add a conditional ``noexcept`` specification to ``std::exchange``","2021-10 (Virtual)","|Complete|","14.0","" "","","","","","" "`P0323R12 `__","``std::expected``","2022-02 (Virtual)","|Complete|","16.0","" -"`P0533R9 `__","``constexpr`` for ```` and ````","2022-02 (Virtual)","|In Progress|","","``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented" +"`P0533R9 `__","``constexpr`` for ```` and ````","2022-02 (Virtual)","|In Progress|","","``isfinite``, ``isinf``, ``isnan``, ``isnormal`` and ``signbit`` are implemented" "`P0627R6 `__","Function to mark unreachable code","2022-02 (Virtual)","|Complete|","15.0","" "`P1206R7 `__","``ranges::to``: A function to convert any range to a container","2022-02 (Virtual)","|Complete|","17.0","" "`P1413R3 `__","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","2022-02 (Virtual)","|Complete|","","``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but clang doesn't issue a diagnostic for deprecated using template declarations." From 1369b39a73391af76cea178b44b0203a44cde4be Mon Sep 17 00:00:00 2001 From: Robin Caloudis Date: Sat, 24 Aug 2024 20:51:54 +0200 Subject: [PATCH 04/10] Use signcopy workaround If constexpr signbit is not available, we make use of signcopy(), which has been constexpr for quite a while in Clang. --- libcxx/include/__math/traits.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h index 9be06b7b8efae9c..077f0aea5b7a914 100644 --- a/libcxx/include/__math/traits.h +++ b/libcxx/include/__math/traits.h @@ -29,19 +29,39 @@ namespace __math { template ::value, int> = 0> _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +// TODO(LLVM 22): Remove `__builtin_copysign`-workaround once support for Clang 19 is dropped. +#if !__has_constexpr_builtin(__builtin_signbit) && _LIBCPP_STD_VER >= 23 + return __builtin_copysign(1.0, __x) == -1.0; +#else return __builtin_signbit(__x); +#endif } _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(float __x) _NOEXCEPT { +// TODO(LLVM 22): Remove `__builtin_copysign`-workaround once support for Clang 19 is dropped. +#if !__has_constexpr_builtin(__builtin_signbit) && _LIBCPP_STD_VER >= 23 + return __builtin_copysign(1.0, __x) == -1.0; +#else return __builtin_signbit(__x); +#endif } _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(double __x) _NOEXCEPT { +// TODO(LLVM 22): Remove `__builtin_copysign`-workaround once support for Clang 19 is dropped. +#if !__has_constexpr_builtin(__builtin_signbit) && _LIBCPP_STD_VER >= 23 + return __builtin_copysign(1.0, __x) == -1.0; +#else return __builtin_signbit(__x); +#endif } _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(long double __x) _NOEXCEPT { +// TODO(LLVM 22): Remove `__builtin_copysign`-workaround once support for Clang 19 is dropped. +#if !__has_constexpr_builtin(__builtin_signbit) && _LIBCPP_STD_VER >= 23 + return __builtin_copysign(1.0, __x) == -1.0; +#else return __builtin_signbit(__x); +#endif } template ::value && is_signed<_A1>::value, int> = 0> From 23559f0532e13f4736a289859827359f3a5614a3 Mon Sep 17 00:00:00 2001 From: Robin Caloudis Date: Sun, 25 Aug 2024 00:39:30 +0200 Subject: [PATCH 05/10] Prefer libcxx overload By using `_LIBCPP_PREFERRED_OVERLOAD` we make sure that a given overload is a better match than an otherwise equally good function declaration. Why is there an equally good function declaration in the first place? Underlying the Windows SDK is the UCRT, the universal C runtime, which clang-cl makes use of. The UCRT should provide only C library headers, but does on top comes with overloads for all cv-unqualified floating point types (float, double, long double) for `std::signbit()` in https://github.com/microsoft/win32metadata/blob/e012b29924c53aa941fc010850b68331b0c3ea80/generation/WinSDK/RecompiledIdlHeaders/ucrt/corecrt_math.h#L309-L322. In a certain way, this can be seen as a deviation from the C standard. We need to work around it. --- libcxx/include/__math/traits.h | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h index 077f0aea5b7a914..e668c5805cea39b 100644 --- a/libcxx/include/__math/traits.h +++ b/libcxx/include/__math/traits.h @@ -37,7 +37,12 @@ _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI boo #endif } -_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(float __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI +#ifdef _LIBCPP_PREFERRED_OVERLOAD +_LIBCPP_PREFERRED_OVERLOAD +#endif + bool + signbit(float __x) _NOEXCEPT { // TODO(LLVM 22): Remove `__builtin_copysign`-workaround once support for Clang 19 is dropped. #if !__has_constexpr_builtin(__builtin_signbit) && _LIBCPP_STD_VER >= 23 return __builtin_copysign(1.0, __x) == -1.0; @@ -46,7 +51,12 @@ _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI boo #endif } -_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI +#ifdef _LIBCPP_PREFERRED_OVERLOAD +_LIBCPP_PREFERRED_OVERLOAD +#endif + bool + signbit(double __x) _NOEXCEPT { // TODO(LLVM 22): Remove `__builtin_copysign`-workaround once support for Clang 19 is dropped. #if !__has_constexpr_builtin(__builtin_signbit) && _LIBCPP_STD_VER >= 23 return __builtin_copysign(1.0, __x) == -1.0; @@ -55,7 +65,12 @@ _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI boo #endif } -_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(long double __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI +#ifdef _LIBCPP_PREFERRED_OVERLOAD +_LIBCPP_PREFERRED_OVERLOAD +#endif + bool + signbit(long double __x) _NOEXCEPT { // TODO(LLVM 22): Remove `__builtin_copysign`-workaround once support for Clang 19 is dropped. #if !__has_constexpr_builtin(__builtin_signbit) && _LIBCPP_STD_VER >= 23 return __builtin_copysign(1.0, __x) == -1.0; From f160b6a5fcecee515cb154aacfdfe22b68dcc6ae Mon Sep 17 00:00:00 2001 From: Robin Caloudis Date: Thu, 29 Aug 2024 08:55:59 +0200 Subject: [PATCH 06/10] Reduce complexity of tests --- .../test/std/numerics/c.math/signbit.pass.cpp | 46 +------------------ libcxx/test/support/type_algorithms.h | 20 +++----- 2 files changed, 9 insertions(+), 57 deletions(-) diff --git a/libcxx/test/std/numerics/c.math/signbit.pass.cpp b/libcxx/test/std/numerics/c.math/signbit.pass.cpp index cdeab92e0836e27..08e785b1d3c61c3 100644 --- a/libcxx/test/std/numerics/c.math/signbit.pass.cpp +++ b/libcxx/test/std/numerics/c.math/signbit.pass.cpp @@ -44,50 +44,11 @@ struct TestFloat { } }; -struct TestUnsignedIntAndFixedWidthChar { +struct TestInt { template static TEST_CONSTEXPR_CXX23 bool test() { assert(!std::signbit(std::numeric_limits::max())); assert(!std::signbit(T(0))); - assert(!std::signbit(std::numeric_limits::lowest())); - - return true; - } - - template - TEST_CONSTEXPR_CXX23 void operator()() { - test(); -#if TEST_STD_VER >= 23 - static_assert(test()); -#endif - } -}; - -struct TestSignedInt { - template - static TEST_CONSTEXPR_CXX23 bool test() { - assert(!std::signbit(std::numeric_limits::max())); - assert(!std::signbit(T(0))); - assert(std::signbit(std::numeric_limits::lowest())); - - return true; - } - - template - TEST_CONSTEXPR_CXX23 void operator()() { - test(); -#if TEST_STD_VER >= 23 - static_assert(test()); -#endif - } -}; - -struct TestVariableWidthChar { - template - static TEST_CONSTEXPR_CXX23 bool test() { - assert(!std::signbit(std::numeric_limits::max())); - assert(!std::signbit(T(0))); - // Signed or unsigned depending on the architecture and platform. if (std::is_unsigned::value) { assert(!std::signbit(std::numeric_limits::lowest())); } else { @@ -113,10 +74,7 @@ struct ConvertibleTo { int main(int, char**) { types::for_each(types::floating_point_types(), TestFloat()); - types::for_each(types::concatenate_t(), - TestUnsignedIntAndFixedWidthChar()); - types::for_each(types::signed_integer_types(), TestSignedInt()); - types::for_each(types::variable_width_character_types(), TestVariableWidthChar()); + types::for_each(types::integral_types(), TestInt()); // Make sure we can call `std::signbit` with convertible types. This checks // whether overloads for all cv-unqualified floating-point types are working diff --git a/libcxx/test/support/type_algorithms.h b/libcxx/test/support/type_algorithms.h index 6b3b9aba11e5ecd..da3d0add4d0c457 100644 --- a/libcxx/test/support/type_algorithms.h +++ b/libcxx/test/support/type_algorithms.h @@ -82,28 +82,22 @@ struct partial_instantiation { // type categories defined in [basic.fundamental] plus extensions (without CV-qualifiers) -using variable_width_character_types = +using character_types = type_list; - -using fixed_width_character_types = type_list< #ifndef TEST_HAS_NO_CHAR8_T - char8_t + , + char8_t #endif #if TEST_STD_VER >= 11 -# ifndef TEST_HAS_NO_CHAR8_T - , -# endif - char16_t, - char32_t + , + char16_t, + char32_t #endif - >; - -using character_types = concatenate_t; + >; using signed_integer_types = type_list Date: Thu, 29 Aug 2024 16:42:57 +0200 Subject: [PATCH 07/10] Apply constexpr only when builtin is --- libcxx/include/__math/traits.h | 13 +++++++------ .../numerics/c.math/constexpr-cxx23-clang.pass.cpp | 7 +++++++ libcxx/test/std/numerics/c.math/signbit.pass.cpp | 3 +++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h index e668c5805cea39b..458bde4b9b2406e 100644 --- a/libcxx/include/__math/traits.h +++ b/libcxx/include/__math/traits.h @@ -28,13 +28,14 @@ namespace __math { // signbit template ::value, int> = 0> -_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { -// TODO(LLVM 22): Remove `__builtin_copysign`-workaround once support for Clang 19 is dropped. -#if !__has_constexpr_builtin(__builtin_signbit) && _LIBCPP_STD_VER >= 23 - return __builtin_copysign(1.0, __x) == -1.0; -#else - return __builtin_signbit(__x); +_LIBCPP_NODISCARD inline +// TODO(LLVM 22): Remove conditional once support for Clang 19 is dropped. +#if !defined(__clang__) || __has_constexpr_builtin(__builtin_signbit) + _LIBCPP_CONSTEXPR_SINCE_CXX23 #endif + _LIBCPP_HIDE_FROM_ABI bool + signbit(_A1 __x) _NOEXCEPT { + return __builtin_signbit(__x); } _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI diff --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp index 20887b8cf2678b3..3f17f21e8c1087a 100644 --- a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp +++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx23-clang.pass.cpp @@ -220,9 +220,16 @@ int main(int, char**) { ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0) == 1); ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0L) == 1); +// TODO(LLVM 22): Remove `__has_constexpr_builtin` conditional once support for Clang 19 is dropped. +#if !__has_constexpr_builtin(__builtin_signbit) + ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1); + ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1); + ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1); +#else ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1); ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1); ASSERT_CONSTEXPR_CXX23(std::signbit(-1.0L) == 1); +#endif ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0f, 0.0f) == 0); ASSERT_NOT_CONSTEXPR_CXX23(std::isgreater(-1.0, 0.0) == 0); diff --git a/libcxx/test/std/numerics/c.math/signbit.pass.cpp b/libcxx/test/std/numerics/c.math/signbit.pass.cpp index 08e785b1d3c61c3..5098fd7548411b3 100644 --- a/libcxx/test/std/numerics/c.math/signbit.pass.cpp +++ b/libcxx/test/std/numerics/c.math/signbit.pass.cpp @@ -11,6 +11,9 @@ // We don't control the implementation on windows // UNSUPPORTED: windows +// These compilers don't support constexpr `__builtin_signbit` yet. +// UNSUPPORTED: clang-17, clang-18, clang-19, apple-clang-15, apple-clang-16 + #include #include #include From 46c26ffe9dfc40587ca8c10c34cc560d10b42551 Mon Sep 17 00:00:00 2001 From: Robin Caloudis Date: Thu, 29 Aug 2024 16:43:41 +0200 Subject: [PATCH 08/10] Remove overloads We will add the overloads in a seperate patch. --- libcxx/include/__math/traits.h | 44 +------------------ .../test/std/numerics/c.math/signbit.pass.cpp | 14 ------ 2 files changed, 1 insertion(+), 57 deletions(-) diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h index 458bde4b9b2406e..9841e7bbc1f8a13 100644 --- a/libcxx/include/__math/traits.h +++ b/libcxx/include/__math/traits.h @@ -30,7 +30,7 @@ namespace __math { template ::value, int> = 0> _LIBCPP_NODISCARD inline // TODO(LLVM 22): Remove conditional once support for Clang 19 is dropped. -#if !defined(__clang__) || __has_constexpr_builtin(__builtin_signbit) +#if defined(_LIBCPP_COMPILER_GCC) || __has_constexpr_builtin(__builtin_signbit) _LIBCPP_CONSTEXPR_SINCE_CXX23 #endif _LIBCPP_HIDE_FROM_ABI bool @@ -38,48 +38,6 @@ _LIBCPP_NODISCARD inline return __builtin_signbit(__x); } -_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI -#ifdef _LIBCPP_PREFERRED_OVERLOAD -_LIBCPP_PREFERRED_OVERLOAD -#endif - bool - signbit(float __x) _NOEXCEPT { -// TODO(LLVM 22): Remove `__builtin_copysign`-workaround once support for Clang 19 is dropped. -#if !__has_constexpr_builtin(__builtin_signbit) && _LIBCPP_STD_VER >= 23 - return __builtin_copysign(1.0, __x) == -1.0; -#else - return __builtin_signbit(__x); -#endif -} - -_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI -#ifdef _LIBCPP_PREFERRED_OVERLOAD -_LIBCPP_PREFERRED_OVERLOAD -#endif - bool - signbit(double __x) _NOEXCEPT { -// TODO(LLVM 22): Remove `__builtin_copysign`-workaround once support for Clang 19 is dropped. -#if !__has_constexpr_builtin(__builtin_signbit) && _LIBCPP_STD_VER >= 23 - return __builtin_copysign(1.0, __x) == -1.0; -#else - return __builtin_signbit(__x); -#endif -} - -_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI -#ifdef _LIBCPP_PREFERRED_OVERLOAD -_LIBCPP_PREFERRED_OVERLOAD -#endif - bool - signbit(long double __x) _NOEXCEPT { -// TODO(LLVM 22): Remove `__builtin_copysign`-workaround once support for Clang 19 is dropped. -#if !__has_constexpr_builtin(__builtin_signbit) && _LIBCPP_STD_VER >= 23 - return __builtin_copysign(1.0, __x) == -1.0; -#else - return __builtin_signbit(__x); -#endif -} - template ::value && is_signed<_A1>::value, int> = 0> _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __x < 0; diff --git a/libcxx/test/std/numerics/c.math/signbit.pass.cpp b/libcxx/test/std/numerics/c.math/signbit.pass.cpp index 5098fd7548411b3..c85033e363ce558 100644 --- a/libcxx/test/std/numerics/c.math/signbit.pass.cpp +++ b/libcxx/test/std/numerics/c.math/signbit.pass.cpp @@ -70,23 +70,9 @@ struct TestInt { } }; -template -struct ConvertibleTo { - operator T() const { return T(); } -}; - 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::signbit` with convertible types. This checks - // whether overloads for all cv-unqualified floating-point types are working - // as expected. - { - assert(!std::signbit(ConvertibleTo())); - assert(!std::signbit(ConvertibleTo())); - assert(!std::signbit(ConvertibleTo())); - } - return 0; } From 236fcf52f5b76b6c982fb6ad4d36c0e5a26cf1a8 Mon Sep 17 00:00:00 2001 From: Robin Caloudis Date: Fri, 30 Aug 2024 18:55:33 +0200 Subject: [PATCH 09/10] Delete update in CSV status file Custom notes are encoded via GitHub issues from now on. --- libcxx/docs/Status/Cxx23Papers.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv index 20bd7b70a0d6199..2c8a91d8401b538 100644 --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -39,7 +39,7 @@ "`P2401R0 `__","Add a conditional ``noexcept`` specification to ``std::exchange``","2021-10 (Virtual)","|Complete|","14.0","" "","","","","","" "`P0323R12 `__","``std::expected``","2022-02 (Virtual)","|Complete|","16.0","" -"`P0533R9 `__","``constexpr`` for ```` and ````","2022-02 (Virtual)","|In Progress|","","``isfinite``, ``isinf``, ``isnan``, ``isnormal`` and ``signbit`` are implemented" +"`P0533R9 `__","``constexpr`` for ```` and ````","2022-02 (Virtual)","|In Progress|","","``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented" "`P0627R6 `__","Function to mark unreachable code","2022-02 (Virtual)","|Complete|","15.0","" "`P1206R7 `__","``ranges::to``: A function to convert any range to a container","2022-02 (Virtual)","|Complete|","17.0","" "`P1413R3 `__","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","2022-02 (Virtual)","|Complete|","","``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but clang doesn't issue a diagnostic for deprecated using template declarations." From b02f0031672da3c42bddd16c0c323edd50724d8c Mon Sep 17 00:00:00 2001 From: Robin Caloudis Date: Sat, 31 Aug 2024 10:31:58 +0200 Subject: [PATCH 10/10] Extract signbit constexprness --- libcxx/include/__math/traits.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h index 9841e7bbc1f8a13..3d4f14fc9cd5523 100644 --- a/libcxx/include/__math/traits.h +++ b/libcxx/include/__math/traits.h @@ -27,24 +27,25 @@ namespace __math { // signbit -template ::value, int> = 0> -_LIBCPP_NODISCARD inline // TODO(LLVM 22): Remove conditional once support for Clang 19 is dropped. #if defined(_LIBCPP_COMPILER_GCC) || __has_constexpr_builtin(__builtin_signbit) - _LIBCPP_CONSTEXPR_SINCE_CXX23 +# define _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_CONSTEXPR_SINCE_CXX23 +#else +# define _LIBCPP_SIGNBIT_CONSTEXPR #endif - _LIBCPP_HIDE_FROM_ABI bool - signbit(_A1 __x) _NOEXCEPT { + +template ::value, int> = 0> +_LIBCPP_NODISCARD inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __builtin_signbit(__x); } template ::value && is_signed<_A1>::value, int> = 0> -_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { return __x < 0; } template ::value && !is_signed<_A1>::value, int> = 0> -_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { +_LIBCPP_NODISCARD inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { return false; }