From 2df00914687875d2141dc912b788b5dc6b27abde Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Fri, 28 Oct 2016 15:14:09 -0700 Subject: Support `-fno-exceptions`. The only thing preventing the non-exception portions of GSL from being used with `-fno-exceptions` is `gsl::narrow`. If we allow the `-fno-exceptions` case to terminate with `gsl::Ensures` instead, the library becomes usable in this case. Note that AFAIK we can only automatically detect this case for Clang. Non-Clang users will need to define `GSL_NO_EXCEPTIONS` themselves when building. Test: Made a test program using gsl::narrow, built and ran with and without -fno-exceptions. Can't add a test because unittest-cpp doesn't seem to support seem to support death tests, but `ctest` still passes for the default (`-fexceptions`) case. Bug: http://b/24296825 Change-Id: Iae72dda03dbd82452fcc296897c73b913a54846a --- gsl/gsl_util | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/gsl/gsl_util b/gsl/gsl_util index f0ac964..a8a41ae 100644 --- a/gsl/gsl_util +++ b/gsl/gsl_util @@ -48,6 +48,18 @@ #endif // _MSC_VER +// AFAIK there's no way to detect in GCC or MSVC. GCC has an __EXCEPTIONS macro, +// but that is only defined if `-fexceptions` is *explicitly* passed on the +// command line; defaulting to exceptions enabled will not set this macro. +// +// Non-Clang users will need to defined GSL_NO_EXCEPTIONS explicitly from the +// command line if they are building with exceptions disabled. +#if defined(__clang__) && !__has_feature(cxx_exceptions) +// If building with -fno-exceptions, we'll fall back to gsl::Ensures in places +// where we would have normally thrown an exception. +#define GSL_NO_EXCEPTIONS +#endif // defined(__has_feature) && !__has_feature(cxx_exceptions) + namespace gsl { // @@ -125,9 +137,14 @@ template inline T narrow(U u) { T t = narrow_cast(u); +#ifndef GSL_NO_EXCEPTIONS if (static_cast(t) != u) throw narrowing_error(); if (!details::is_same_signedness::value && ((t < T{}) != (u < U{}))) throw narrowing_error(); +#else + Ensures(static_cast(t) == u); + Ensures(!(!details::is_same_signedness::value && ((t < T{}) != (u < U{})))); +#endif return t; } @@ -135,30 +152,30 @@ inline T narrow(U u) // at() - Bounds-checked way of accessing static arrays, std::array, std::vector // template -constexpr T& at(T (&arr)[N], size_t index) +constexpr T& at(T (&arr)[N], std::ptrdiff_t index) { - Expects(index < N); - return arr[index]; + Expects(index >= 0 && index < narrow_cast(N)); + return arr[static_cast(index)]; } template -constexpr T& at(std::array& arr, size_t index) +constexpr T& at(std::array& arr, std::ptrdiff_t index) { - Expects(index < N); - return arr[index]; + Expects(index >= 0 && index < narrow_cast(N)); + return arr[static_cast(index)]; } template -constexpr typename Cont::value_type& at(Cont& cont, size_t index) +constexpr typename Cont::value_type& at(Cont& cont, std::ptrdiff_t index) { - Expects(index < cont.size()); - return cont[index]; + Expects(index >= 0 && index < narrow_cast(cont.size())); + return cont[static_cast(index)]; } template -constexpr const T& at(std::initializer_list cont, size_t index) +constexpr const T& at(std::initializer_list cont, std::ptrdiff_t index) { - Expects(index < cont.size()); + Expects(index >= 0 && index < narrow_cast(cont.size())); return *(cont.begin() + index); } -- cgit v1.2.3