1/////////////////////////////////////////////////////////////////////////////// 2// 3// Copyright (c) 2015 Microsoft Corporation. All rights reserved. 4// 5// This code is licensed under the MIT License (MIT). 6// 7// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 13// THE SOFTWARE. 14// 15/////////////////////////////////////////////////////////////////////////////// 16 17#ifndef GSL_CONTRACTS_H 18#define GSL_CONTRACTS_H 19 20#include <exception> 21#include <stdexcept> // for logic_error 22 23// 24// make suppress attributes parse for some compilers 25// Hopefully temporary until suppression standardization occurs 26// 27#if defined(__clang__) 28#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] 29#else 30#if defined(_MSC_VER) 31#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] 32#else 33#define GSL_SUPPRESS(x) 34#endif // _MSC_VER 35#endif // __clang__ 36 37// 38// Temporary until MSVC STL supports no-exceptions mode. 39// Currently terminate is a no-op in this mode, so we add termination behavior back 40// 41#if defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS 42#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND 43#include <intrin.h> 44#define RANGE_CHECKS_FAILURE 0 45 46#if defined(__clang__) 47#pragma clang diagnostic push 48#pragma clang diagnostic ignored "-Winvalid-noreturn" 49#endif 50 51#endif 52 53// 54// There are three configuration options for this GSL implementation's behavior 55// when pre/post conditions on the GSL types are violated: 56// 57// 1. GSL_TERMINATE_ON_CONTRACT_VIOLATION: std::terminate will be called (default) 58// 2. GSL_THROW_ON_CONTRACT_VIOLATION: a gsl::fail_fast exception will be thrown 59// 3. GSL_UNENFORCED_ON_CONTRACT_VIOLATION: nothing happens 60// 61#if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) || defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) || \ 62 defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)) 63#define GSL_TERMINATE_ON_CONTRACT_VIOLATION 64#endif 65 66#define GSL_STRINGIFY_DETAIL(x) #x 67#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) 68 69#if defined(__clang__) || defined(__GNUC__) 70#define GSL_LIKELY(x) __builtin_expect(!!(x), 1) 71#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0) 72#else 73#define GSL_LIKELY(x) (!!(x)) 74#define GSL_UNLIKELY(x) (!!(x)) 75#endif 76 77// 78// GSL_ASSUME(cond) 79// 80// Tell the optimizer that the predicate cond must hold. It is unspecified 81// whether or not cond is actually evaluated. 82// 83#ifdef _MSC_VER 84#define GSL_ASSUME(cond) __assume(cond) 85#elif defined(__GNUC__) 86#define GSL_ASSUME(cond) ((cond) ? static_cast<void>(0) : __builtin_unreachable()) 87#else 88#define GSL_ASSUME(cond) static_cast<void>((cond) ? 0 : 0) 89#endif 90 91// 92// GSL.assert: assertions 93// 94 95namespace gsl 96{ 97struct fail_fast : public std::logic_error 98{ 99 explicit fail_fast(char const* const message) : std::logic_error(message) {} 100}; 101 102namespace details 103{ 104#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) 105 106 typedef void (__cdecl *terminate_handler)(); 107 108 GSL_SUPPRESS(f.6) // NO-FORMAT: attribute 109 [[noreturn]] inline void __cdecl default_terminate_handler() 110 { 111 __fastfail(RANGE_CHECKS_FAILURE); 112 } 113 114 inline gsl::details::terminate_handler& get_terminate_handler() noexcept 115 { 116 static terminate_handler handler = &default_terminate_handler; 117 return handler; 118 } 119 120#endif 121 122 [[noreturn]] inline void terminate() noexcept 123 { 124#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) 125 (*gsl::details::get_terminate_handler())(); 126#else 127 std::terminate(); 128#endif 129 } 130 131#if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) 132 133 template <typename Exception> 134 [[noreturn]] void throw_exception(Exception&&) noexcept 135 { 136 gsl::details::terminate(); 137 } 138 139#else 140 141 template <typename Exception> 142 [[noreturn]] void throw_exception(Exception&& exception) 143 { 144 throw std::forward<Exception>(exception); 145 } 146 147#endif // GSL_TERMINATE_ON_CONTRACT_VIOLATION 148 149} // namespace details 150} // namespace gsl 151 152#if defined(GSL_THROW_ON_CONTRACT_VIOLATION) 153 154#define GSL_CONTRACT_CHECK(type, cond) \ 155 (GSL_LIKELY(cond) ? static_cast<void>(0) \ 156 : gsl::details::throw_exception(gsl::fail_fast( \ 157 "GSL: " type " failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__)))) 158 159#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) 160 161#define GSL_CONTRACT_CHECK(type, cond) \ 162 (GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate()) 163 164#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION) 165 166#define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond) 167 168#endif // GSL_THROW_ON_CONTRACT_VIOLATION 169 170#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond) 171#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond) 172 173#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__) 174#pragma clang diagnostic pop 175#endif 176 177#endif // GSL_CONTRACTS_H 178