From 152f43f24cdff31196947912ebef1d352190426f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 5 May 2026 13:13:23 -0400 Subject: [PATCH 1/7] Remove CUDA C++23 testing --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dfd72d8d..7f23b2dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,9 +91,9 @@ jobs: cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY git submodule update --init tools/boostdep python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY - - name: Test C++20/23 + - name: Test C++20 run: | - for std in 20 23; do + for std in 20; do echo "======== Testing C++${std} ========" cd ../boost-root rm -rf __build__ From 51a394fe7961660527cdaa4ae5287dd694882ad7 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 5 May 2026 13:26:23 -0400 Subject: [PATCH 2/7] As special handling for Intel compilers for 0 detection --- .../boost/safe_numbers/detail/float_basis.hpp | 49 ++++++++++++++++--- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/include/boost/safe_numbers/detail/float_basis.hpp b/include/boost/safe_numbers/detail/float_basis.hpp index f1e603e9..26f36437 100644 --- a/include/boost/safe_numbers/detail/float_basis.hpp +++ b/include/boost/safe_numbers/detail/float_basis.hpp @@ -437,6 +437,35 @@ BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] constexpr auto constexpr_isnormal(c return !(val == T{} || constexpr_isinf(val) || constexpr_isnan(val) || constexpr_abs(val) < std::numeric_limits::min()); } +// Bit-pattern test for true zero, used in IEEE 754 error classification where +// a subnormal must not be confused with zero, such as with optimized builds on the Intel Compiler +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wfloat-equal" +#elif defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + +template +BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] constexpr auto is_true_zero(const T val) noexcept -> bool +{ +#if defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER) + using bit_type = std::conditional_t, std::uint32_t, std::uint64_t>; + constexpr bit_type sign_mask {bit_type{1} << (std::numeric_limits::digits - 1)}; + const auto bits {std::bit_cast(val)}; + return static_cast(bits & ~sign_mask) == bit_type{0}; +#else + return val == T{}; +#endif +} + +#ifdef __clang__ +# pragma clang diagnostic pop +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#endif + template BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] constexpr auto constexpr_fpclassify(const T val) noexcept -> int { @@ -990,7 +1019,7 @@ BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] auto checked_float_multiplication(c return error_category::invalid_op; } // 7.2.c: multiplication of zero by an infinity, in either order - if ((lhs == T{} && constexpr_isinf(rhs)) || (constexpr_isinf(lhs) && rhs == T{})) + if ((is_true_zero(lhs) && constexpr_isinf(rhs)) || (constexpr_isinf(lhs) && is_true_zero(rhs))) { return error_category::invalid_op; } @@ -1243,8 +1272,10 @@ BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] auto checked_float_division(const T { return error_category::invalid_op; } - // 7.2.b: division of zero by zero - if (lhs == T{} && rhs == T{}) + // 7.2.b: division of zero by zero. Use is_true_zero so a denormal divisor + // flushed to zero by DAZ (Intel C++ optimized builds, etc.) does not get + // misclassified as a true zero here. + if (is_true_zero(lhs) && is_true_zero(rhs)) { return error_category::invalid_op; } @@ -1255,9 +1286,10 @@ BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] auto checked_float_division(const T } // Section 7.3: divideByZero is signaled when a finite non-zero dividend - // is divided by zero. The 0/0 case was already handled above as invalid_op, + // is divided by zero. + // The 0/0 case was already handled above as invalid_op, // and inf/0 falls through to the section 6.1 infinity classification below. - if (rhs == T{} && !constexpr_isinf(lhs) && !constexpr_isnan(lhs)) + if (is_true_zero(rhs) && !constexpr_isinf(lhs) && !constexpr_isnan(lhs)) { return error_category::divide_by_zero; } @@ -1552,15 +1584,16 @@ BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] auto checked_float_modulo(const T l { return error_category::invalid_op; } - // 7.2.f sub-case 1: zero modulo zero (matches operator/ treatment of 0/0) - if (lhs == T{} && rhs == T{}) + // 7.2.f sub-case 1: zero modulo zero (matches operator/ treatment of 0/0). + // is_true_zero so a denormal flushed to zero by DAZ does not match here. + if (is_true_zero(lhs) && is_true_zero(rhs)) { return error_category::invalid_op; } // Modulo by zero with a finite non-zero dividend. Strict IEEE 7.2.f // classifies this as invalid_op, but we surface it separately to mirror // operator/'s divide-by-zero behavior. - if (rhs == T{} && !constexpr_isinf(lhs) && !constexpr_isnan(lhs)) + if (is_true_zero(rhs) && !constexpr_isinf(lhs) && !constexpr_isnan(lhs)) { return error_category::divide_by_zero; } From 0ef456a824caca39e249b2781cec00c9bd43fc99 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 5 May 2026 13:41:08 -0400 Subject: [PATCH 3/7] Remove MINGW32 from CI --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7f23b2dd..5c8be938 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,6 +37,7 @@ jobs: name: Run Boost.CI uses: boostorg/boost-ci/.github/workflows/reusable.yml@master with: + exclude_os: 'MINGW32' # We blow the stack with the library exclude_compiler: 'clang-3.5,clang-3.6,clang-3.7,clang-3.8,clang-3.9,clang-4.0,clang-5.0,clang-6.0,clang-7, clang-8,clang-9,clang-10,clang-11,clang-12, gcc-4.7,gcc-4.8,gcc-4.9,gcc-5,gcc-6,gcc-7,gcc-8,gcc-9,gcc-10' From 273169b1708f27c776c3a275e81e8b21b00f04a0 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 5 May 2026 14:01:18 -0400 Subject: [PATCH 4/7] Try re-arrange --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c8be938..15b884cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,10 +37,10 @@ jobs: name: Run Boost.CI uses: boostorg/boost-ci/.github/workflows/reusable.yml@master with: - exclude_os: 'MINGW32' # We blow the stack with the library exclude_compiler: 'clang-3.5,clang-3.6,clang-3.7,clang-3.8,clang-3.9,clang-4.0,clang-5.0,clang-6.0,clang-7, clang-8,clang-9,clang-10,clang-11,clang-12, gcc-4.7,gcc-4.8,gcc-4.9,gcc-5,gcc-6,gcc-7,gcc-8,gcc-9,gcc-10' + exclude_os: 'MINGW32' # We blow the stack with the library # Example of customization: # with: # enable_reflection: true From 9ad6ccc537a58d50506a5b4d4f0bb399c241705b Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 5 May 2026 16:14:42 -0400 Subject: [PATCH 5/7] Replace exclude_os with enable_mingw: false --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 15b884cc..47f610bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: exclude_compiler: 'clang-3.5,clang-3.6,clang-3.7,clang-3.8,clang-3.9,clang-4.0,clang-5.0,clang-6.0,clang-7, clang-8,clang-9,clang-10,clang-11,clang-12, gcc-4.7,gcc-4.8,gcc-4.9,gcc-5,gcc-6,gcc-7,gcc-8,gcc-9,gcc-10' - exclude_os: 'MINGW32' # We blow the stack with the library + enable_mingw: false # We blow the stack on the 32-bit with the library # Example of customization: # with: # enable_reflection: true From 92f364d9902ba9bd73ce36d720e89d06a832f556 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 5 May 2026 16:18:48 -0400 Subject: [PATCH 6/7] Ignore MSVC warnings --- .../boost/safe_numbers/detail/float_basis.hpp | 52 ++++++++++++++----- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/include/boost/safe_numbers/detail/float_basis.hpp b/include/boost/safe_numbers/detail/float_basis.hpp index 26f36437..6159d95f 100644 --- a/include/boost/safe_numbers/detail/float_basis.hpp +++ b/include/boost/safe_numbers/detail/float_basis.hpp @@ -509,6 +509,12 @@ enum class error_category namespace impl { +// It's ok that we overflow since we will check post-op +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4756) +#endif + // Follows the conventions from IEEE 754 section 6 and 7 on what should happen with mixed non-finite operation: // 1) Saturation to positive infinity -> Overflow // 2) Saturation to negative infinity -> Underflow @@ -554,6 +560,10 @@ BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] auto checked_float_addition(const T BOOST_SAFE_NUMBERS_UNREACHABLE; // LCOV_EXCL_LINE } +#ifdef _MSC_VER +# pragma warning(pop) +#endif + template BOOST_SAFE_NUMBERS_HOST_DEVICE constexpr auto throw_overflow_add() -> void { @@ -752,6 +762,12 @@ BOOST_SAFE_NUMBERS_HOST_DEVICE namespace impl { +// It's ok that we overflow since we will check post-op +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4756) +#endif + // See comment above on checked_float_add template BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] auto checked_float_subtraction(const T lhs, const T rhs, T& res) -> error_category @@ -792,6 +808,10 @@ BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] auto checked_float_subtraction(cons BOOST_SAFE_NUMBERS_UNREACHABLE; // LCOV_EXCL_LINE } +#ifdef _MSC_VER +# pragma warning(pop) +#endif + template BOOST_SAFE_NUMBERS_HOST_DEVICE constexpr auto throw_overflow_sub() -> void { @@ -992,11 +1012,14 @@ namespace impl { // Our comparison to zero is fine #ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wfloat-equal" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wfloat-equal" #elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wfloat-equal" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wfloat-equal" +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable:4756) #endif // See comment above on checked_float_addition @@ -1040,9 +1063,11 @@ BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] auto checked_float_multiplication(c } #ifdef __clang__ -#pragma clang diagnostic pop +# pragma clang diagnostic pop #elif defined(__GNUC__) -#pragma GCC diagnostic pop +# pragma GCC diagnostic pop +#elif defined(_MSC_VER) +# pragma warning(pop) #endif template @@ -1245,14 +1270,16 @@ namespace impl { // Our comparison to zero is fine #ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wfloat-equal" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wfloat-equal" #elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wfloat-equal" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wfloat-equal" +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable:4756) #endif - // See comment above on checked_float_addition template BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] auto checked_float_division(const T lhs, const T rhs, T& res) -> error_category @@ -1313,9 +1340,10 @@ BOOST_SAFE_NUMBERS_HOST_DEVICE [[nodiscard]] auto checked_float_division(const T #pragma clang diagnostic pop #elif defined(__GNUC__) #pragma GCC diagnostic pop +#elif defined(_MSC_VER) +#pragma warning(pop) #endif - template BOOST_SAFE_NUMBERS_HOST_DEVICE constexpr auto throw_overflow_div() -> void { From 53e06d8eecf4c8bf019660fdf98f39db749f0912 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 5 May 2026 16:46:13 -0400 Subject: [PATCH 7/7] Explicit naming to fix subdir failure on Windows --- test/cmake_test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cmake_test/CMakeLists.txt b/test/cmake_test/CMakeLists.txt index 6d888304..3e0885ba 100644 --- a/test/cmake_test/CMakeLists.txt +++ b/test/cmake_test/CMakeLists.txt @@ -75,6 +75,6 @@ target_link_libraries(quick Boost::safe_numbers) target_compile_features(quick PRIVATE cxx_std_20) enable_testing() -add_test(quick quick) +add_test(NAME quick COMMAND quick) add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $)