blob: 131fa8b151647ca7292df91cfd3d8f293365def6 [file] [log] [blame]
Brian Silvermana6f7ce02018-07-07 15:04:00 -07001///////////////////////////////////////////////////////////////////////////////
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// Temporary until MSVC STL supports no-exceptions mode.
25// Currently terminate is a no-op in this mode, so we add termination behavior back
26//
27#if defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
28#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
29#endif
30
31//
32// There are three configuration options for this GSL implementation's behavior
33// when pre/post conditions on the GSL types are violated:
34//
35// 1. GSL_TERMINATE_ON_CONTRACT_VIOLATION: std::terminate will be called (default)
36// 2. GSL_THROW_ON_CONTRACT_VIOLATION: a gsl::fail_fast exception will be thrown
37// 3. GSL_UNENFORCED_ON_CONTRACT_VIOLATION: nothing happens
38//
39#if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) || defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) || \
40 defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION))
41#define GSL_TERMINATE_ON_CONTRACT_VIOLATION
42#endif
43
44#define GSL_STRINGIFY_DETAIL(x) #x
45#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
46
47#if defined(__clang__) || defined(__GNUC__)
48#define GSL_LIKELY(x) __builtin_expect(!!(x), 1)
49#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0)
50#else
51#define GSL_LIKELY(x) (!!(x))
52#define GSL_UNLIKELY(x) (!!(x))
53#endif
54
55//
56// GSL_ASSUME(cond)
57//
58// Tell the optimizer that the predicate cond must hold. It is unspecified
59// whether or not cond is actually evaluated.
60//
61#ifdef _MSC_VER
62#define GSL_ASSUME(cond) __assume(cond)
63#elif defined(__GNUC__)
64#define GSL_ASSUME(cond) ((cond) ? static_cast<void>(0) : __builtin_unreachable())
65#else
66#define GSL_ASSUME(cond) static_cast<void>((cond) ? 0 : 0)
67#endif
68
69//
70// GSL.assert: assertions
71//
72
73namespace gsl
74{
75struct fail_fast : public std::logic_error
76{
77 explicit fail_fast(char const* const message) : std::logic_error(message) {}
78};
79
80namespace details
81{
82#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
83
84 typedef void (__cdecl *terminate_handler)();
85
86 inline gsl::details::terminate_handler& get_terminate_handler() noexcept
87 {
88 static terminate_handler handler = &abort;
89 return handler;
90 }
91
92#endif
93
94 [[noreturn]] inline void terminate() noexcept
95 {
96#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
97 (*gsl::details::get_terminate_handler())();
98#else
99 std::terminate();
100#endif
101 }
102
103#if defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
104
105 template <typename Exception>
106 [[noreturn]] void throw_exception(Exception&&)
107 {
108 gsl::details::terminate();
109 }
110
111#else
112
113 template <typename Exception>
114 [[noreturn]] void throw_exception(Exception&& exception)
115 {
116 throw std::forward<Exception>(exception);
117 }
118
119#endif
120
121} // namespace details
122} // namespace gsl
123
124#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
125
126#define GSL_CONTRACT_CHECK(type, cond) \
127 (GSL_LIKELY(cond) ? static_cast<void>(0) \
128 : gsl::details::throw_exception(gsl::fail_fast( \
129 "GSL: " type " failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__))))
130
131#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
132
133#define GSL_CONTRACT_CHECK(type, cond) \
134 (GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())
135
136#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)
137
138#define GSL_CONTRACT_CHECK(type, cond) GSL_ASSUME(cond)
139
140#endif
141
142#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond)
143#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)
144
145#endif // GSL_CONTRACTS_H