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 95 namespace gsl 96 { 97 struct fail_fast : public std::logic_error 98 { 99 explicit fail_fast(char const* const message) : std::logic_error(message) {} 100 }; 101 102 namespace 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