diff --git a/CMakeLists.txt b/CMakeLists.txt index db299e61..e3abf0fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ foreach(p endforeach() option(BENCHMARK_ENABLE_TESTING "Enable testing of the benchmark library." ON) +option(BENCHMARK_ENABLE_EXCEPTIONS "Enable the use of exceptions in the benchmark library." ON) option(BENCHMARK_ENABLE_LTO "Enable link time optimisation of the benchmark library." OFF) option(BENCHMARK_USE_LIBCXX "Build and test using libc++ as the standard library." OFF) # Make sure we can import out CMake functions @@ -39,6 +40,10 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") add_definitions(-D_CRT_SECURE_NO_WARNINGS) + if (NOT BENCHMARK_ENABLE_EXCEPTIONS) + add_cxx_compiler_flag(-EHs-) + add_cxx_compiler_flag(-EHa-) + endif() # Link time optimisation if (BENCHMARK_ENABLE_LTO) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") @@ -80,6 +85,9 @@ else() add_cxx_compiler_flag(-Wshorten-64-to-32) add_cxx_compiler_flag(-Wfloat-equal) add_cxx_compiler_flag(-fstrict-aliasing) + if (NOT BENCHMARK_ENABLE_EXCEPTIONS) + add_cxx_compiler_flag(-fno-exceptions) + endif() if (NOT BENCHMARK_USE_LIBCXX) add_cxx_compiler_flag(-Wzero-as-null-pointer-constant) endif() @@ -162,7 +170,10 @@ cxx_feature_check(POSIX_REGEX) if(NOT HAVE_STD_REGEX AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX) message(FATAL_ERROR "Failed to determine the source files for the regular expression backend") endif() - +if (NOT BENCHMARK_ENABLE_EXCEPTIONS AND HAVE_STD_REGEX + AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX) + message(WARNING "Using std::regex with exceptions disabled is not fully supported") +endif() cxx_feature_check(STEADY_CLOCK) # Ensure we have pthreads find_package(Threads REQUIRED) diff --git a/src/internal_macros.h b/src/internal_macros.h index e8efcbb3..46913f41 100644 --- a/src/internal_macros.h +++ b/src/internal_macros.h @@ -39,4 +39,9 @@ #define BENCHMARK_OS_LINUX 1 #endif +#if !__has_feature(cxx_exceptions) && !defined(__cpp_exceptions) \ + && !defined(__EXCEPTIONS) +#define BENCHMARK_HAS_NO_EXCEPTIONS +#endif + #endif // BENCHMARK_INTERNAL_MACROS_H_ diff --git a/src/re.h b/src/re.h index af4a498c..01e97365 100644 --- a/src/re.h +++ b/src/re.h @@ -15,6 +15,15 @@ #ifndef BENCHMARK_RE_H_ #define BENCHMARK_RE_H_ +#include "internal_macros.h" + +// Prefer C regex libraries when compiling w/o exceptions so that we can +// correctly report errors. +#if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && defined(HAVE_STD_REGEX) && \ + (defined(HAVE_GNU_POSIX_REGEX) || defined(HAVE_POSIX_REGEX)) +#undef HAVE_STD_REGEX +#endif + #if defined(HAVE_STD_REGEX) #include #elif defined(HAVE_GNU_POSIX_REGEX) @@ -62,15 +71,20 @@ class Regex { #if defined(HAVE_STD_REGEX) inline bool Regex::Init(const std::string& spec, std::string* error) { +#ifdef BENCHMARK_HAS_NO_EXCEPTIONS + ((void)error); // suppress unused warning +#else try { +#endif re_ = std::regex(spec, std::regex_constants::extended); - init_ = true; +#ifndef BENCHMARK_HAS_NO_EXCEPTIONS } catch (const std::regex_error& e) { if (error) { *error = e.what(); } } +#endif return init_; }