Skip to content

Add user and automatic configuration macro to disable exceptions #972

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 2 additions & 0 deletions doc/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
18 changes: 17 additions & 1 deletion doc/modules/ROOT/pages/api_reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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`]

5 changes: 5 additions & 0 deletions doc/modules/ROOT/pages/config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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:

Expand All @@ -44,6 +48,7 @@ Again, it must be defined before inclusion of decimal headers like so:

- `BOOST_DECIMAL_DEC_EVAL_METHOD`: See <cfloat> 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.
Expand Down
28 changes: 28 additions & 0 deletions include/boost/decimal/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 4 additions & 3 deletions include/boost/decimal/fmt_format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <fmt/format.h>
#include <fmt/base.h>
#include <boost/decimal/detail/config.hpp>
#include <boost/decimal/charconv.hpp>
#include <algorithm>
#include <format>
Expand Down Expand Up @@ -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
}
}

Expand Down
5 changes: 3 additions & 2 deletions include/boost/decimal/format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
#ifndef BOOST_DECIMAL_FORMAT_HPP
#define BOOST_DECIMAL_FORMAT_HPP

// Many compilers seem to have <format> with completly broken support so narrow down our support range
// Many compilers seem to have <format> 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 <boost/decimal/detail/config.hpp>
#include <boost/decimal/charconv.hpp>
#include <algorithm>
#include <format>
Expand Down Expand Up @@ -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
}
}
Expand Down
5 changes: 3 additions & 2 deletions test/test_big_uints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <boost/decimal.hpp>

#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.
Expand All @@ -20,7 +22,6 @@ int main()
// Propagates up from boost.math
#define _SILENCE_CXX23_DENORM_DEPRECATION_WARNING

#include <boost/decimal.hpp>
#include <boost/decimal/detail/u256.hpp>

#if defined(__clang__)
Expand Down
6 changes: 5 additions & 1 deletion test/test_decimal32_fast_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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

Expand Down
6 changes: 5 additions & 1 deletion test/test_decimal32_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions test/test_snprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -227,7 +227,7 @@ int main()
test_bootstrap<decimal128_t>();

// 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

Expand Down
6 changes: 5 additions & 1 deletion test/test_strtod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ void test_strtod_edges()
BOOST_TEST(isnan(boost::decimal::strtod<T>(junk_str, nullptr))) && BOOST_TEST_EQ(errno, EINVAL);
}

#ifndef BOOST_DECIMAL_DISABLE_EXCEPTIONS

template <typename T>
void test_locales()
{
Expand Down Expand Up @@ -164,6 +166,8 @@ void test_locales()
BOOST_TEST_EQ(valdiation_value, val);
}

#endif

template <typename T>
void test_spot(const char* str, T val)
{
Expand Down Expand Up @@ -278,7 +282,7 @@ int main()
test_alloc<decimal64_t>();

// 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<decimal32_t>();
test_locales<decimal64_t>();
test_locales<decimal128_t>();
Expand Down
Loading