/////////////////////////////////////////////////////////////////////////////// // // 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. // /////////////////////////////////////////////////////////////////////////////// #ifndef GSL_CONTRACTS_H #define GSL_CONTRACTS_H // // 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(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)) #define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND #include #define RANGE_CHECKS_FAILURE 0 #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Winvalid-noreturn" #endif // defined(__clang__) #else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && // !_HAS_EXCEPTIONS)) #include #endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && // !_HAS_EXCEPTIONS)) // // make suppress attributes parse for some compilers // Hopefully temporary until suppression standardization occurs // #if defined(__clang__) #define GSL_SUPPRESS(x) [[gsl::suppress("x")]] #else #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #define GSL_SUPPRESS(x) [[gsl::suppress(x)]] #else #define GSL_SUPPRESS(x) #endif // _MSC_VER #endif // __clang__ #define GSL_STRINGIFY_DETAIL(x) #x #define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) // // GSL.assert: assertions // namespace gsl { namespace details { #if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) typedef void(__cdecl* terminate_handler)(); // clang-format off GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // clang-format on [[noreturn]] inline void __cdecl default_terminate_handler() { __fastfail(RANGE_CHECKS_FAILURE); } inline gsl::details::terminate_handler& get_terminate_handler() noexcept { static terminate_handler handler = &default_terminate_handler; return handler; } #endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) [[noreturn]] inline void terminate() noexcept { #if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) (*gsl::details::get_terminate_handler())(); #else std::terminate(); #endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) } } // namespace details class contract_group { public: #if defined __cpp_noexcept_function_type using handler = void (*)() noexcept; #else // VESTIGIAL, remove when no longer needed for downlevel compilers using handler = void (*)(); #endif constexpr contract_group (handler h = nullptr) : chandler(normalize(h)) { } constexpr auto set_handler(handler h) -> handler { auto old = chandler; chandler = normalize(h); return old; } constexpr auto get_handler() const -> handler { return chandler; } constexpr auto expects (bool b) -> void { assertion(b); } constexpr auto ensures (bool b) -> void { assertion(b); } private: constexpr auto assertion(bool b) -> void { if (!b) chandler(); } constexpr auto normalize(handler h) -> handler { return h ? h : []()noexcept{}; } handler chandler; }; // By default, there is one violation handler per translation unit. // Defining GSL_GLOBAL_CONTRACT_VIOLATION_HANDLERS and compiling as // C++17 (or later) opts into using a global violation handler. #if defined GSL_GLOBAL_CONTRACT_VIOLATION_HANDLERS && __cplusplus >= 201703L #define GSL_CONTRACT_VIOLATION_GRANULARITY inline #else #define GSL_CONTRACT_VIOLATION_GRANULARITY static #endif auto GSL_CONTRACT_VIOLATION_GRANULARITY Default = contract_group( #if defined GSL_UNENFORCED_ON_CONTRACT_VIOLATION // use default == null handler #else // if defined GSL_TERMINATE_ON_CONTRACT_VIOLATION &gsl::details::terminate #endif ); auto GSL_CONTRACT_VIOLATION_GRANULARITY Bounds = Default; auto GSL_CONTRACT_VIOLATION_GRANULARITY Null = Default; auto GSL_CONTRACT_VIOLATION_GRANULARITY Testing = Default; } // namespace gsl #define Expects(cond, kind) kind.expects(cond) #define Ensures(cond, kind) kind.ensures(cond) #if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__) #pragma clang diagnostic pop #endif #endif // GSL_CONTRACTS_H