aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Albert <danalbert@google.com>2016-10-28 15:14:09 -0700
committerDan Albert <danalbert@google.com>2016-10-28 15:14:09 -0700
commit2df00914687875d2141dc912b788b5dc6b27abde (patch)
tree9b100e0dbd1de6589f13db155332e6560b7a1d48
parente15c08c681ff00dc3e270c9c0ad737e086abfd76 (diff)
downloadplatform_external_Microsoft-GSL-2df00914687875d2141dc912b788b5dc6b27abde.tar.gz
platform_external_Microsoft-GSL-2df00914687875d2141dc912b788b5dc6b27abde.tar.bz2
platform_external_Microsoft-GSL-2df00914687875d2141dc912b788b5dc6b27abde.zip
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
-rw-r--r--gsl/gsl_util39
1 files 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 <class T, class U>
inline T narrow(U u)
{
T t = narrow_cast<T>(u);
+#ifndef GSL_NO_EXCEPTIONS
if (static_cast<U>(t) != u) throw narrowing_error();
if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))
throw narrowing_error();
+#else
+ Ensures(static_cast<U>(t) == u);
+ Ensures(!(!details::is_same_signedness<T, U>::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 <class T, size_t N>
-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<std::ptrdiff_t>(N));
+ return arr[static_cast<size_t>(index)];
}
template <class T, size_t N>
-constexpr T& at(std::array<T, N>& arr, size_t index)
+constexpr T& at(std::array<T, N>& arr, std::ptrdiff_t index)
{
- Expects(index < N);
- return arr[index];
+ Expects(index >= 0 && index < narrow_cast<std::ptrdiff_t>(N));
+ return arr[static_cast<size_t>(index)];
}
template <class Cont>
-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<std::ptrdiff_t>(cont.size()));
+ return cont[static_cast<typename Cont::size_type>(index)];
}
template <class T>
-constexpr const T& at(std::initializer_list<T> cont, size_t index)
+constexpr const T& at(std::initializer_list<T> cont, std::ptrdiff_t index)
{
- Expects(index < cont.size());
+ Expects(index >= 0 && index < narrow_cast<std::ptrdiff_t>(cont.size()));
return *(cont.begin() + index);
}