diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6dc96101..cffcff72 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" diff --git a/doc/modules/ROOT/nav.adoc b/doc/modules/ROOT/nav.adoc index efd6aff1..539bb1a3 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] diff --git a/doc/modules/ROOT/pages/api_reference.adoc b/doc/modules/ROOT/pages/api_reference.adoc index ef392745..8082c98c 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 60db8344..d23ebc7c 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: @@ -18,6 +19,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: @@ -44,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. diff --git a/include/boost/decimal/detail/config.hpp b/include/boost/decimal/detail/config.hpp index 76f08316..0416269d 100644 --- a/include/boost/decimal/detail/config.hpp +++ b/include/boost/decimal/detail/config.hpp @@ -354,4 +354,32 @@ 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) +# 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 + +#endif // Exceptions + #endif // BOOST_DECIMAL_DETAIL_CONFIG_HPP diff --git a/include/boost/decimal/fmt_format.hpp b/include/boost/decimal/fmt_format.hpp index 18bd9588..37c6a2ad 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 102aa29f..07418970 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 } } diff --git a/test/test_big_uints.cpp b/test/test_big_uints.cpp index 9463c39e..7adac665 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 17634b0c..4a695a97 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 33c72d47..be05ae85 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 36724656..645c6678 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 c9282316..c54c07cd 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();