diff options
author | Anna Gringauze <annagrin@microsoft.com> | 2018-03-15 16:00:08 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-15 16:00:08 -0700 |
commit | d846fe50a3f0bb7767c7e087a05f4be95f4da0ec (patch) | |
tree | 53a695dda67c9a5b034ad64c814baa8b3e2d434c /include | |
parent | c6bf25a5f6463047a59df3cc5b6fd18c8766c6a8 (diff) | |
download | platform_external_Microsoft-GSL-d846fe50a3f0bb7767c7e087a05f4be95f4da0ec.tar.gz platform_external_Microsoft-GSL-d846fe50a3f0bb7767c7e087a05f4be95f4da0ec.tar.bz2 platform_external_Microsoft-GSL-d846fe50a3f0bb7767c7e087a05f4be95f4da0ec.zip |
Enable usage of gsl::narrow with exceptions disabled (#640)
* Enable usage of gsl::narrow with exceptions disabled
This solution uses the approach of boost::asio to enabling usage of the
library in environments where exception usage is either prohibited
or not feasible (due to code size constraints). A function template
gsl::throw_exception has been added, which in a normal environment just
throws the exception. However, when GSL_TERMINATE_ON_CONTRACT_VIOLATION
is defined the function is only declared by gsl and the definition of
this function template must be supplied by the library's user.
Closes: #468
Signed-off-by: Damian Jarek <damian.jarek93@gmail.com>
Addition:
- understand STL no exception macro
- use function static variable to set termination handler in kernel mode
- add compile-only tests for no-exception mode
* added termination tests and fixed bugs
* disabled warning C4577 for msvc 2015
Diffstat (limited to 'include')
-rw-r--r-- | include/gsl/gsl_assert | 60 | ||||
-rw-r--r-- | include/gsl/gsl_util | 4 |
2 files changed, 58 insertions, 6 deletions
diff --git a/include/gsl/gsl_assert b/include/gsl/gsl_assert index eeb3473..2bda149 100644 --- a/include/gsl/gsl_assert +++ b/include/gsl/gsl_assert @@ -21,6 +21,14 @@ #include <stdexcept> // for logic_error // +// Temporary until MSVC STL supports no-exceptions mode. +// Currently terminate is a no-op in this mode, so we add termination behavior back +// +#if defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS +#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND +#endif + +// // There are three configuration options for this GSL implementation's behavior // when pre/post conditions on the GSL types are violated: // @@ -68,18 +76,62 @@ struct fail_fast : public std::logic_error { explicit fail_fast(char const* const message) : std::logic_error(message) {} }; -} + +namespace details +{ +#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + + typedef void (*terminate_handler)(); + + inline gsl::details::terminate_handler& get_terminate_handler() noexcept + { + static terminate_handler handler = &abort; + return handler; + } + +#endif + + [[noreturn]] inline void terminate() noexcept + { +#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + (*gsl::details::get_terminate_handler())(); +#else + std::terminate(); +#endif + } + +#if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) + + template <typename Exception> + [[noreturn]] void throw_exception(Exception&&) + { + gsl::details::terminate(); + } + +#else + + template <typename Exception> + [[noreturn]] void throw_exception(Exception&& exception) + { + throw exception; + } + +#endif + +} // namespace details +} // namespace gsl #if defined(GSL_THROW_ON_CONTRACT_VIOLATION) #define GSL_CONTRACT_CHECK(type, cond) \ (GSL_LIKELY(cond) ? static_cast<void>(0) \ - : throw gsl::fail_fast("GSL: " type " failure at " __FILE__ \ - ": " GSL_STRINGIFY(__LINE__))) + : gsl::details::throw_exception(gsl::fail_fast( \ + "GSL: " type " failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__)))) #elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) -#define GSL_CONTRACT_CHECK(type, cond) (GSL_LIKELY(cond) ? static_cast<void>(0) : std::terminate()) +#define GSL_CONTRACT_CHECK(type, cond) \ + (GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate()) #elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION) diff --git a/include/gsl/gsl_util b/include/gsl/gsl_util index 1aa8ba6..2ca171b 100644 --- a/include/gsl/gsl_util +++ b/include/gsl/gsl_util @@ -110,9 +110,9 @@ template <class T, class U> T narrow(U u) { T t = narrow_cast<T>(u); - if (static_cast<U>(t) != u) throw narrowing_error(); + if (static_cast<U>(t) != u) gsl::details::throw_exception(narrowing_error()); if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{}))) - throw narrowing_error(); + gsl::details::throw_exception(narrowing_error()); return t; } |