Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/GSL.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Gringauze <annagrin@microsoft.com>2018-03-16 02:00:08 +0300
committerGitHub <noreply@github.com>2018-03-16 02:00:08 +0300
commitd846fe50a3f0bb7767c7e087a05f4be95f4da0ec (patch)
tree53a695dda67c9a5b034ad64c814baa8b3e2d434c
parentc6bf25a5f6463047a59df3cc5b6fd18c8766c6a8 (diff)
Enable usage of gsl::narrow with exceptions disabled (#640)v1.0.0
* 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
-rw-r--r--include/gsl/gsl_assert60
-rw-r--r--include/gsl/gsl_util4
-rw-r--r--tests/CMakeLists.txt61
-rw-r--r--tests/no_exception_ensure_tests.cpp53
-rw-r--r--tests/no_exception_throw_tests.cpp51
5 files changed, 223 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;
}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 86ce5a4..0e08d77 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -101,3 +101,64 @@ add_gsl_test(utils_tests)
add_gsl_test(owner_tests)
add_gsl_test(byte_tests)
add_gsl_test(algorithm_tests)
+
+
+# No exception tests
+
+foreach(flag_var
+ CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+ CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+ STRING (REGEX REPLACE "/EHsc" "" ${flag_var} "${${flag_var}}")
+endforeach(flag_var)
+
+# this interface adds compile options to how the tests are run
+# please try to keep entries ordered =)
+add_library(gsl_tests_config_noexcept INTERFACE)
+target_compile_options(gsl_tests_config_noexcept INTERFACE
+ $<$<CXX_COMPILER_ID:MSVC>:
+ /D_HAS_EXCEPTIONS=0
+ /wd4702
+ /wd4577
+ /W4
+ /WX
+ >
+ $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:
+ -fno-strict-aliasing
+ -fno-exceptions
+ -Wall
+ -Wcast-align
+ -Wconversion
+ -Wctor-dtor-privacy
+ -Werror
+ -Wextra
+ -Wno-missing-braces
+ -Wnon-virtual-dtor
+ -Wold-style-cast
+ -Woverloaded-virtual
+ -Wpedantic
+ -Wshadow
+ -Wsign-conversion
+ >
+)
+
+# set definitions for tests
+target_compile_definitions(gsl_tests_config_noexcept INTERFACE
+ GSL_TERMINATE_ON_CONTRACT_VIOLATION
+)
+
+function(add_gsl_test_noexcept name)
+ add_executable(${name} ${name}.cpp)
+ target_link_libraries(${name}
+ GSL
+ gsl_tests_config_noexcept
+ )
+ add_test(
+ ${name}
+ ${name}
+ )
+ # group all tests under GSL_tests_noexcept
+ set_property(TARGET ${name} PROPERTY FOLDER "GSL_tests_noexcept")
+endfunction()
+
+add_gsl_test_noexcept(no_exception_throw_tests)
+add_gsl_test_noexcept(no_exception_ensure_tests)
diff --git a/tests/no_exception_ensure_tests.cpp b/tests/no_exception_ensure_tests.cpp
new file mode 100644
index 0000000..5da021e
--- /dev/null
+++ b/tests/no_exception_ensure_tests.cpp
@@ -0,0 +1,53 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <cstdlib> // for std::exit
+#include <gsl/span> // for span
+
+int operator_subscript_no_throw()
+{
+ int arr[10];
+ gsl::span<int> sp { arr };
+ return sp[11];
+}
+
+
+void test_terminate()
+{
+ std::exit(0);
+}
+
+void setup_termination_handler()
+{
+#if defined(_MSC_VER)
+
+ auto& handler = gsl::details::get_terminate_handler();
+ handler = &test_terminate;
+
+#else
+
+ std::set_terminate(test_terminate);
+
+#endif
+}
+
+
+int main()
+{
+ setup_termination_handler();
+ operator_subscript_no_throw();
+ return -1;
+}
diff --git a/tests/no_exception_throw_tests.cpp b/tests/no_exception_throw_tests.cpp
new file mode 100644
index 0000000..dd4e994
--- /dev/null
+++ b/tests/no_exception_throw_tests.cpp
@@ -0,0 +1,51 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <cstdlib> // for std::exit
+#include <gsl/gsl_util> // for narrow
+
+int narrow_no_throw()
+{
+ long long bigNumber = 0x0fffffffffffffff;
+ return gsl::narrow<int>(bigNumber);
+}
+
+void test_terminate()
+{
+ std::exit(0);
+}
+
+void setup_termination_handler()
+{
+#if defined(_MSC_VER)
+
+ auto& handler = gsl::details::get_terminate_handler();
+ handler = &test_terminate;
+
+#else
+
+ std::set_terminate(test_terminate);
+
+#endif
+}
+
+
+int main()
+{
+ setup_termination_handler();
+ narrow_no_throw();
+ return -1;
+}