From 7192571a7b52e37e64210775c16ab9fee39ed0b1 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 6 Aug 2025 10:35:01 -0400 Subject: [PATCH 1/8] Define macro for disabled exceptions --- include/boost/decimal/detail/config.hpp | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/include/boost/decimal/detail/config.hpp b/include/boost/decimal/detail/config.hpp index 76f08316f..8ba790f8e 100644 --- a/include/boost/decimal/detail/config.hpp +++ b/include/boost/decimal/detail/config.hpp @@ -354,4 +354,30 @@ typedef unsigned __int128 builtin_uint128_t; # endif #endif +// Detect if we can throw or not +// First check if the user said no explicitly +// Then check if it's been disabled elsewhere + +#ifdef BOOST_DECIMAL_DISABLE_EXCEPTIONS + +# define BOOST_DECIMAL_THROW_EXCEPTION(expr) + +#else + +# ifdef _MSC_VER +# ifdef _CPPUNWIND +# define BOOST_DECIMAL_THROW_EXCEPTION(expr) throw expr; +# else +# define BOOST_DECIMAL_THROW_EXCEPTION(expr) +# endif +# else +# ifdef __EXCEPTIONS +# define BOOST_DECIMAL_THROW_EXCEPTION(expr) throw expr; +# else +# define BOOST_DECIMAL_THROW_EXCEPTION(expr) +# endif +#endif + +#endif // Exceptions + #endif // BOOST_DECIMAL_DETAIL_CONFIG_HPP From b2e8536c7974e13fdb4b45fcf3bd3f210a9c8442 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 6 Aug 2025 10:43:40 -0400 Subject: [PATCH 2/8] Replace throw with throw macro --- include/boost/decimal/fmt_format.hpp | 7 ++++--- include/boost/decimal/format.hpp | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/boost/decimal/fmt_format.hpp b/include/boost/decimal/fmt_format.hpp index 18bd95889..37c6a2ad0 100644 --- a/include/boost/decimal/fmt_format.hpp +++ b/include/boost/decimal/fmt_format.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -93,10 +94,10 @@ constexpr auto parse_impl(ParseContext &ctx) case 'a': fmt = chars_format::hex; break; - // LCOV_EXCL_START + // LCOV_EXCL_START default: - throw std::logic_error("Invalid format specifier"); - // LCOV_EXCL_STOP + BOOST_DECIMAL_THROW_EXCEPTION(std::logic_error("Invalid format specifier")); + // LCOV_EXCL_STOP } } diff --git a/include/boost/decimal/format.hpp b/include/boost/decimal/format.hpp index 102aa29fc..074189708 100644 --- a/include/boost/decimal/format.hpp +++ b/include/boost/decimal/format.hpp @@ -5,12 +5,13 @@ #ifndef BOOST_DECIMAL_FORMAT_HPP #define BOOST_DECIMAL_FORMAT_HPP -// Many compilers seem to have with completly broken support so narrow down our support range +// Many compilers seem to have with completely broken support so narrow down our support range #if (__cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)) && !defined(BOOST_DECIMAL_DISABLE_CLIB) && \ ((defined(__GNUC__) && __GNUC__ >= 13) || (defined(__clang__) && __clang_major__ >= 18) || (defined(_MSC_VER) && _MSC_VER >= 1940)) #define BOOST_DECIMAL_HAS_FORMAT_SUPPORT +#include #include #include #include @@ -91,7 +92,7 @@ constexpr auto parse_impl(ParseContext &ctx) break; // LCOV_EXCL_START default: - throw std::format_error("Invalid format specifier"); + BOOST_DECIMAL_THROW_EXCEPTION(std::format_error("Invalid format specifier")); // LCOV_EXCL_STOP } } From b4aa46734d2e068dd57dfb02f9eb19286841a77f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 6 Aug 2025 10:52:26 -0400 Subject: [PATCH 3/8] Add no exceptions runner to CI --- .github/workflows/ci.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6dc961010..cffcff728 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,6 +119,14 @@ jobs: container: ubuntu:24.04 install: - g++-14-multilib + - toolset: gcc-14 + cxxstd: "03,11,14,17,20,23,2c" + cxxflags: -fno-exceptions + address_model: "64" + os: ubuntu-latest + container: ubuntu:24.04 + install: + - g++-14-multilib - toolset: gcc-14 cxxstd: "03,11,14,17,20,23,2c" address_model: "32" From 63a547069e0d83e7be3f14ddebefc9be1dbcf974 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 6 Aug 2025 11:09:25 -0400 Subject: [PATCH 4/8] Document disabling exceptions --- doc/modules/ROOT/pages/config.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/modules/ROOT/pages/config.adoc b/doc/modules/ROOT/pages/config.adoc index 60db8344b..4d192d965 100644 --- a/doc/modules/ROOT/pages/config.adoc +++ b/doc/modules/ROOT/pages/config.adoc @@ -18,6 +18,9 @@ The following configuration macros are available: - `BOOST_DECIMAL_DISABLE_CLIB`: Defines both of the above macros. In testing this reduces ROM usage by ~50% and can be useful if running on embedded platforms. +- `BOOST_DECIMAL_DISABLE_EXCEPTIONS`: This allows the user to disable any calls to `throw`. +This macro will also be set automatically in the presence of `-fno-exceptions` or various `/EH` flags on MSVC. + - `BOOST_DECIMAL_ALLOW_IMPLICIT_CONVERSIONS`: Allows a binary floating-point type (e.g. `double`) to be implicitly converted to a decimal floating point type. This option is not recommended, but can be useful if you want to use specific functionality from the standard library with internal conversions such as: From aef8efd802549cc884c1b65c0ae1891c5eee9d2e Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 6 Aug 2025 11:18:43 -0400 Subject: [PATCH 5/8] Automatically define no exceptions macro --- include/boost/decimal/detail/config.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/decimal/detail/config.hpp b/include/boost/decimal/detail/config.hpp index 8ba790f8e..0416269db 100644 --- a/include/boost/decimal/detail/config.hpp +++ b/include/boost/decimal/detail/config.hpp @@ -369,12 +369,14 @@ typedef unsigned __int128 builtin_uint128_t; # define BOOST_DECIMAL_THROW_EXCEPTION(expr) throw expr; # else # define BOOST_DECIMAL_THROW_EXCEPTION(expr) +# define BOOST_DECIMAL_DISABLE_EXCEPTIONS # endif # else # ifdef __EXCEPTIONS # define BOOST_DECIMAL_THROW_EXCEPTION(expr) throw expr; # else # define BOOST_DECIMAL_THROW_EXCEPTION(expr) +# define BOOST_DECIMAL_DISABLE_EXCEPTIONS # endif #endif From 700733fa5652ca6150d18c4624464b60503d7950 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 6 Aug 2025 11:23:29 -0400 Subject: [PATCH 6/8] Disable specific tests that require exception support --- test/test_big_uints.cpp | 5 +++-- test/test_decimal32_fast_stream.cpp | 6 +++++- test/test_decimal32_stream.cpp | 6 +++++- test/test_snprintf.cpp | 4 ++-- test/test_strtod.cpp | 6 +++++- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/test/test_big_uints.cpp b/test/test_big_uints.cpp index 9463c39ec..7adac665f 100644 --- a/test/test_big_uints.cpp +++ b/test/test_big_uints.cpp @@ -2,7 +2,9 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#if defined(__MINGW32__) +#include + +#if defined(__MINGW32__) || defined(BOOST_DECIMAL_DISABLE_EXCEPTIONS) // TODO(ckormanyos) disable -Werror in BJAM specifically for this file, as it gets // a hard-coded, non-removable warning (-Werror) propagated up from Multiprecision. @@ -20,7 +22,6 @@ int main() // Propagates up from boost.math #define _SILENCE_CXX23_DENORM_DEPRECATION_WARNING -#include #include #if defined(__clang__) diff --git a/test/test_decimal32_fast_stream.cpp b/test/test_decimal32_fast_stream.cpp index 17634b0c8..4a695a975 100644 --- a/test/test_decimal32_fast_stream.cpp +++ b/test/test_decimal32_fast_stream.cpp @@ -111,6 +111,8 @@ void test_ostream() BOOST_TEST_CSTR_EQ(neg_snan.str().c_str(), "-nan(snan)"); } +#ifndef BOOST_DECIMAL_DISABLE_EXCEPTIONS + void test_locales() { const char buffer[] = "1,1897e+02"; @@ -142,13 +144,15 @@ void test_locales() BOOST_TEST_CSTR_EQ(out.str().c_str(), buffer); } +#endif + int main() { test_istream(); test_ostream(); // Homebrew GCC does not support locales - #if !(defined(__GNUC__) && __GNUC__ >= 5 && defined(__APPLE__)) && !defined(BOOST_DECIMAL_QEMU_TEST) + #if !(defined(__GNUC__) && __GNUC__ >= 5 && defined(__APPLE__)) && !defined(BOOST_DECIMAL_QEMU_TEST) && !defined(BOOST_DECIMAL_DISABLE_EXCEPTIONS) test_locales(); #endif diff --git a/test/test_decimal32_stream.cpp b/test/test_decimal32_stream.cpp index 33c72d47f..be05ae854 100644 --- a/test/test_decimal32_stream.cpp +++ b/test/test_decimal32_stream.cpp @@ -111,6 +111,8 @@ void test_ostream() BOOST_TEST_CSTR_EQ(neg_snan.str().c_str(), "-nan(snan)"); } +#ifndef BOOST_DECIMAL_DISABLE_EXCEPTIONS + void test_locales() { const char buffer[] = "1,1897e+02"; @@ -142,13 +144,15 @@ void test_locales() BOOST_TEST_CSTR_EQ(out.str().c_str(), buffer); } +#endif + int main() { test_istream(); test_ostream(); // Homebrew GCC does not support locales - #if !(defined(__GNUC__) && __GNUC__ >= 5 && defined(__APPLE__)) && !defined(BOOST_DECIMAL_QEMU_TEST) + #if !(defined(__GNUC__) && __GNUC__ >= 5 && defined(__APPLE__)) && !defined(BOOST_DECIMAL_QEMU_TEST) && !defined(BOOST_DECIMAL_DISABLE_EXCEPTIONS) test_locales(); #endif diff --git a/test/test_snprintf.cpp b/test/test_snprintf.cpp index 367246562..645c6678d 100644 --- a/test/test_snprintf.cpp +++ b/test/test_snprintf.cpp @@ -80,7 +80,7 @@ void test_uppercase(T value, const char* format_sprintf, chars_format fmt = char BOOST_TEST_EQ(num_bytes, r.ptr - charconv_buffer); } -#if !(defined(__APPLE__) && defined(__GNUC__) && !defined(__clang__)) +#if !(defined(__APPLE__) && defined(__GNUC__) && !defined(__clang__)) && !defined(BOOST_DECIMAL_DISABLE_EXCEPTIONS) void test_locales() { const char buffer[] = "1,1897e+02"; @@ -227,7 +227,7 @@ int main() test_bootstrap(); // Homebrew gcc on mac does not support locales - #if !(defined(__APPLE__) && defined(__GNUC__) && !defined(__clang__)) && !defined(BOOST_DECIMAL_QEMU_TEST) + #if !(defined(__APPLE__) && defined(__GNUC__) && !defined(__clang__)) && !defined(BOOST_DECIMAL_QEMU_TEST) && !defined(BOOST_DECIMAL_DISABLE_EXCEPTIONS) test_locales(); #endif diff --git a/test/test_strtod.cpp b/test/test_strtod.cpp index c92823165..c54c07cdf 100644 --- a/test/test_strtod.cpp +++ b/test/test_strtod.cpp @@ -137,6 +137,8 @@ void test_strtod_edges() BOOST_TEST(isnan(boost::decimal::strtod(junk_str, nullptr))) && BOOST_TEST_EQ(errno, EINVAL); } +#ifndef BOOST_DECIMAL_DISABLE_EXCEPTIONS + template void test_locales() { @@ -164,6 +166,8 @@ void test_locales() BOOST_TEST_EQ(valdiation_value, val); } +#endif + template void test_spot(const char* str, T val) { @@ -278,7 +282,7 @@ int main() test_alloc(); // Homebrew GCC does not support locales - #if !(defined(__GNUC__) && __GNUC__ >= 5 && defined(__APPLE__)) && !defined(BOOST_DECIMAL_QEMU_TEST) + #if !(defined(__GNUC__) && __GNUC__ >= 5 && defined(__APPLE__)) && !defined(BOOST_DECIMAL_QEMU_TEST) && !defined(BOOST_DECIMAL_DISABLE_EXCEPTIONS) test_locales(); test_locales(); test_locales(); From 62831bfcbb80749b64b6a98ccad164a33b8c6f65 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 6 Aug 2025 12:06:14 -0400 Subject: [PATCH 7/8] Improve API reference section for macros --- doc/modules/ROOT/pages/api_reference.adoc | 18 +++++++++++++++++- doc/modules/ROOT/pages/config.adoc | 2 ++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/doc/modules/ROOT/pages/api_reference.adoc b/doc/modules/ROOT/pages/api_reference.adoc index ef392745c..8082c98ce 100644 --- a/doc/modules/ROOT/pages/api_reference.adoc +++ b/doc/modules/ROOT/pages/api_reference.adoc @@ -46,4 +46,20 @@ enums, constants and macros that are provided in this library. [#api_ref_macros] == Macros -See: xref:config.adoc[configuration] +=== User Configuration + +- xref:config.adoc#configuration_user[`BOOST_DECIMAL_DISABLE_CASSERT`] +- xref:config.adoc#configuration_user[`BOOST_DECIMAL_DISABLE_IOSTREAM`] +- xref:config.adoc#configuration_user[`BOOST_DECIMAL_DISABLE_CLIB`] +- xref:config.adoc#configuration_user[`BOOST_DECIMAL_DISABLE_EXCEPTIONS`] +- xref:config.adoc#configuration_user[`BOOST_DECIMAL_ALLOW_IMPLICIT_CONVERSIONS`] +- xref:config.adoc#configuration_user[`BOOST_DECIMAL_FAST_MATH`] +- xref:config.adoc#configuration_user[`BOOST_DECIMAL_DEC_EVAL_METHOD`] + +=== Automatic Configuration + +- xref:config.adoc#configuration_automatic[`BOOST_DECIMAL_CXX20_CONSTEXPR`] +- xref:config.adoc#configuration_automatic[`BOOST_DECIMAL_CONSTEXPR`] +- xref:config.adoc#configuration_automatic[`BOOST_DECIMAL_HAS_STD_CHARCONV`] +- xref:config.adoc#configuration_automatic[`BOOST_DECIMAL_HAS_STD_STRING_VIEW`] + diff --git a/doc/modules/ROOT/pages/config.adoc b/doc/modules/ROOT/pages/config.adoc index 4d192d965..d23ebc7ce 100644 --- a/doc/modules/ROOT/pages/config.adoc +++ b/doc/modules/ROOT/pages/config.adoc @@ -8,6 +8,7 @@ https://www.boost.org/LICENSE_1_0.txt = Configuration Macros :idprefix: config_ +[#configuration_user] == User Configurable Macros The following configuration macros are available: @@ -47,6 +48,7 @@ Again, it must be defined before inclusion of decimal headers like so: - `BOOST_DECIMAL_DEC_EVAL_METHOD`: See section for explanation +[#configuration_automatic] == Automatic Configuration Macros - `BOOST_DECIMAL_CXX20_CONSTEXPR`: This is defined to `constexpr` when compiling with C++20 or greater, otherwise it expands to nothing. From c24610be278cd2e372e6f108ea88e200497ce22c Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 6 Aug 2025 12:07:46 -0400 Subject: [PATCH 8/8] Update nav bar for user and automatic config --- doc/modules/ROOT/nav.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/modules/ROOT/nav.adoc b/doc/modules/ROOT/nav.adoc index efd6aff12..539bb1a30 100644 --- a/doc/modules/ROOT/nav.adoc +++ b/doc/modules/ROOT/nav.adoc @@ -45,6 +45,8 @@ * xref:functional.adoc[] * xref:limits.adoc[] * xref:config.adoc[] +** xref:config.adoc#configuration_user[User Configuration] +** xref:config.adoc#configuration_automatic[Automatic Configuration] * xref:benchmarks.adoc[] ** xref:benchmarks.adoc#x64_linux_benchmarks[x64 Linux] ** xref:benchmarks.adoc#x64_windows_benchmarks[x64 Windows]