1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _LIBCPP___DEBUG |
11 | #define _LIBCPP___DEBUG |
12 | |
13 | #include <__assert> |
14 | #include <__config> |
15 | #include <cstddef> |
16 | #include <type_traits> |
17 | |
18 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
19 | # pragma GCC system_header |
20 | #endif |
21 | |
22 | // Catch invalid uses of the legacy _LIBCPP_DEBUG toggle. |
23 | #if defined(_LIBCPP_DEBUG) && _LIBCPP_DEBUG != 0 && !defined(_LIBCPP_ENABLE_DEBUG_MODE) |
24 | # error "Enabling the debug mode now requires having configured the library with support for the debug mode" |
25 | #endif |
26 | |
27 | #if defined(_LIBCPP_ENABLE_DEBUG_MODE) && !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY) |
28 | # define _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY |
29 | #endif |
30 | |
31 | #ifdef _LIBCPP_ENABLE_DEBUG_MODE |
32 | # define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(::std::__libcpp_is_constant_evaluated() || (x), m) |
33 | #else |
34 | # define _LIBCPP_DEBUG_ASSERT(x, m) ((void)0) |
35 | #endif |
36 | |
37 | #if defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_BUILDING_LIBRARY) |
38 | |
39 | _LIBCPP_BEGIN_NAMESPACE_STD |
40 | |
41 | struct _LIBCPP_TYPE_VIS __c_node; |
42 | |
43 | struct _LIBCPP_TYPE_VIS __i_node |
44 | { |
45 | void* __i_; |
46 | __i_node* __next_; |
47 | __c_node* __c_; |
48 | |
49 | __i_node(const __i_node&) = delete; |
50 | __i_node& operator=(const __i_node&) = delete; |
51 | |
52 | _LIBCPP_INLINE_VISIBILITY |
53 | __i_node(void* __i, __i_node* __next, __c_node* __c) |
54 | : __i_(__i), __next_(__next), __c_(__c) {} |
55 | ~__i_node(); |
56 | }; |
57 | |
58 | struct _LIBCPP_TYPE_VIS __c_node |
59 | { |
60 | void* __c_; |
61 | __c_node* __next_; |
62 | __i_node** beg_; |
63 | __i_node** end_; |
64 | __i_node** cap_; |
65 | |
66 | __c_node(const __c_node&) = delete; |
67 | __c_node& operator=(const __c_node&) = delete; |
68 | |
69 | _LIBCPP_INLINE_VISIBILITY |
70 | explicit __c_node(void* __c, __c_node* __next) |
71 | : __c_(__c), __next_(__next), beg_(nullptr), end_(nullptr), cap_(nullptr) {} |
72 | virtual ~__c_node(); |
73 | |
74 | virtual bool __dereferenceable(const void*) const = 0; |
75 | virtual bool __decrementable(const void*) const = 0; |
76 | virtual bool __addable(const void*, ptrdiff_t) const = 0; |
77 | virtual bool __subscriptable(const void*, ptrdiff_t) const = 0; |
78 | |
79 | void __add(__i_node* __i); |
80 | _LIBCPP_HIDDEN void __remove(__i_node* __i); |
81 | }; |
82 | |
83 | template <class _Cont> |
84 | struct _C_node |
85 | : public __c_node |
86 | { |
87 | explicit _C_node(void* __c, __c_node* __n) |
88 | : __c_node(__c, __n) {} |
89 | |
90 | virtual bool __dereferenceable(const void*) const; |
91 | virtual bool __decrementable(const void*) const; |
92 | virtual bool __addable(const void*, ptrdiff_t) const; |
93 | virtual bool __subscriptable(const void*, ptrdiff_t) const; |
94 | }; |
95 | |
96 | template <class _Cont> |
97 | inline bool |
98 | _C_node<_Cont>::__dereferenceable(const void* __i) const |
99 | { |
100 | typedef typename _Cont::const_iterator iterator; |
101 | const iterator* __j = static_cast<const iterator*>(__i); |
102 | _Cont* _Cp = static_cast<_Cont*>(__c_); |
103 | return _Cp->__dereferenceable(__j); |
104 | } |
105 | |
106 | template <class _Cont> |
107 | inline bool |
108 | _C_node<_Cont>::__decrementable(const void* __i) const |
109 | { |
110 | typedef typename _Cont::const_iterator iterator; |
111 | const iterator* __j = static_cast<const iterator*>(__i); |
112 | _Cont* _Cp = static_cast<_Cont*>(__c_); |
113 | return _Cp->__decrementable(__j); |
114 | } |
115 | |
116 | template <class _Cont> |
117 | inline bool |
118 | _C_node<_Cont>::__addable(const void* __i, ptrdiff_t __n) const |
119 | { |
120 | typedef typename _Cont::const_iterator iterator; |
121 | const iterator* __j = static_cast<const iterator*>(__i); |
122 | _Cont* _Cp = static_cast<_Cont*>(__c_); |
123 | return _Cp->__addable(__j, __n); |
124 | } |
125 | |
126 | template <class _Cont> |
127 | inline bool |
128 | _C_node<_Cont>::__subscriptable(const void* __i, ptrdiff_t __n) const |
129 | { |
130 | typedef typename _Cont::const_iterator iterator; |
131 | const iterator* __j = static_cast<const iterator*>(__i); |
132 | _Cont* _Cp = static_cast<_Cont*>(__c_); |
133 | return _Cp->__subscriptable(__j, __n); |
134 | } |
135 | |
136 | class _LIBCPP_TYPE_VIS __libcpp_db |
137 | { |
138 | __c_node** __cbeg_; |
139 | __c_node** __cend_; |
140 | size_t __csz_; |
141 | __i_node** __ibeg_; |
142 | __i_node** __iend_; |
143 | size_t __isz_; |
144 | |
145 | explicit __libcpp_db(); |
146 | public: |
147 | __libcpp_db(const __libcpp_db&) = delete; |
148 | __libcpp_db& operator=(const __libcpp_db&) = delete; |
149 | |
150 | ~__libcpp_db(); |
151 | |
152 | class __db_c_iterator; |
153 | class __db_c_const_iterator; |
154 | class __db_i_iterator; |
155 | class __db_i_const_iterator; |
156 | |
157 | __db_c_const_iterator __c_end() const; |
158 | __db_i_const_iterator __i_end() const; |
159 | |
160 | typedef __c_node*(_InsertConstruct)(void*, void*, __c_node*); |
161 | |
162 | template <class _Cont> |
163 | _LIBCPP_INLINE_VISIBILITY static __c_node* __create_C_node(void *__mem, void *__c, __c_node *__next) { |
164 | return ::new (__mem) _C_node<_Cont>(__c, __next); |
165 | } |
166 | |
167 | template <class _Cont> |
168 | _LIBCPP_INLINE_VISIBILITY |
169 | void __insert_c(_Cont* __c) |
170 | { |
171 | __insert_c(static_cast<void*>(__c), &__create_C_node<_Cont>); |
172 | } |
173 | |
174 | void __insert_i(void* __i); |
175 | void __insert_c(void* __c, _InsertConstruct* __fn); |
176 | void __erase_c(void* __c); |
177 | |
178 | void __insert_ic(void* __i, const void* __c); |
179 | void __iterator_copy(void* __i, const void* __i0); |
180 | void __erase_i(void* __i); |
181 | |
182 | void* __find_c_from_i(void* __i) const; |
183 | void __invalidate_all(void* __c); |
184 | __c_node* __find_c_and_lock(void* __c) const; |
185 | __c_node* __find_c(void* __c) const; |
186 | void unlock() const; |
187 | |
188 | void swap(void* __c1, void* __c2); |
189 | |
190 | |
191 | bool __dereferenceable(const void* __i) const; |
192 | bool __decrementable(const void* __i) const; |
193 | bool __addable(const void* __i, ptrdiff_t __n) const; |
194 | bool __subscriptable(const void* __i, ptrdiff_t __n) const; |
195 | bool __less_than_comparable(const void* __i, const void* __j) const; |
196 | private: |
197 | _LIBCPP_HIDDEN |
198 | __i_node* __insert_iterator(void* __i); |
199 | _LIBCPP_HIDDEN |
200 | __i_node* __find_iterator(const void* __i) const; |
201 | |
202 | friend _LIBCPP_FUNC_VIS __libcpp_db* __get_db(); |
203 | }; |
204 | |
205 | _LIBCPP_FUNC_VIS __libcpp_db* __get_db(); |
206 | _LIBCPP_FUNC_VIS const __libcpp_db* __get_const_db(); |
207 | |
208 | _LIBCPP_END_NAMESPACE_STD |
209 | |
210 | #endif // defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_BUILDING_LIBRARY) |
211 | |
212 | _LIBCPP_BEGIN_NAMESPACE_STD |
213 | |
214 | template <class _Tp> |
215 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_insert_c(_Tp* __c) { |
216 | #ifdef _LIBCPP_ENABLE_DEBUG_MODE |
217 | if (!__libcpp_is_constant_evaluated()) |
218 | __get_db()->__insert_c(__c); |
219 | #else |
220 | (void)(__c); |
221 | #endif |
222 | } |
223 | |
224 | template <class _Tp> |
225 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_insert_i(_Tp* __i) { |
226 | #ifdef _LIBCPP_ENABLE_DEBUG_MODE |
227 | if (!__libcpp_is_constant_evaluated()) |
228 | __get_db()->__insert_i(__i); |
229 | #else |
230 | (void)(__i); |
231 | #endif |
232 | } |
233 | |
234 | template <class _Tp> |
235 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_erase_c(_Tp* __c) { |
236 | #ifdef _LIBCPP_ENABLE_DEBUG_MODE |
237 | if (!__libcpp_is_constant_evaluated()) |
238 | __get_db()->__erase_c(__c); |
239 | #else |
240 | (void)(__c); |
241 | #endif |
242 | } |
243 | |
244 | template <class _Tp> |
245 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_swap(_Tp* __lhs, _Tp* __rhs) { |
246 | #ifdef _LIBCPP_ENABLE_DEBUG_MODE |
247 | if (!__libcpp_is_constant_evaluated()) |
248 | __get_db()->swap(__lhs, __rhs); |
249 | #else |
250 | (void)(__lhs); |
251 | (void)(__rhs); |
252 | #endif |
253 | } |
254 | |
255 | template <class _Tp> |
256 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_invalidate_all(_Tp* __c) { |
257 | #ifdef _LIBCPP_ENABLE_DEBUG_MODE |
258 | if (!__libcpp_is_constant_evaluated()) |
259 | __get_db()->__invalidate_all(__c); |
260 | #else |
261 | (void)(__c); |
262 | #endif |
263 | } |
264 | |
265 | _LIBCPP_END_NAMESPACE_STD |
266 | |
267 | #endif // _LIBCPP___DEBUG |
268 | |