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_H 11#define _LIBCPP_DEBUG_H 12 13#include <__config> 14#include <iosfwd> 15#include <type_traits> 16 17#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 18# pragma GCC system_header 19#endif 20 21#if _LIBCPP_DEBUG_LEVEL >= 1 || defined(_LIBCPP_BUILDING_LIBRARY) 22# include <cstddef> 23# include <cstdio> 24# include <cstdlib> 25#endif 26 27#if _LIBCPP_DEBUG_LEVEL == 0 28# define _LIBCPP_DEBUG_ASSERT(x, m) ((void)0) 29# define _LIBCPP_ASSERT_IMPL(x, m) ((void)0) 30#elif _LIBCPP_DEBUG_LEVEL == 1 31# define _LIBCPP_DEBUG_ASSERT(x, m) ((void)0) 32# define _LIBCPP_ASSERT_IMPL(x, m) ((x) ? (void)0 : ::std::__libcpp_debug_function(::std::__libcpp_debug_info(__FILE__, __LINE__, #x, m))) 33#elif _LIBCPP_DEBUG_LEVEL == 2 34# define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(::std::__libcpp_is_constant_evaluated() || (x), m) 35# define _LIBCPP_ASSERT_IMPL(x, m) ((x) ? (void)0 : ::std::__libcpp_debug_function(::std::__libcpp_debug_info(__FILE__, __LINE__, #x, m))) 36#else 37# error _LIBCPP_DEBUG_LEVEL must be one of 0, 1, 2 38#endif 39 40#if !defined(_LIBCPP_ASSERT) 41# define _LIBCPP_ASSERT(x, m) _LIBCPP_ASSERT_IMPL(x, m) 42#endif 43 44_LIBCPP_BEGIN_NAMESPACE_STD 45 46struct _LIBCPP_TEMPLATE_VIS __libcpp_debug_info { 47 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 48 __libcpp_debug_info() 49 : __file_(nullptr), __line_(-1), __pred_(nullptr), __msg_(nullptr) {} 50 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 51 __libcpp_debug_info(const char* __f, int __l, const char* __p, const char* __m) 52 : __file_(__f), __line_(__l), __pred_(__p), __msg_(__m) {} 53 54 _LIBCPP_FUNC_VIS string what() const; 55 56 const char* __file_; 57 int __line_; 58 const char* __pred_; 59 const char* __msg_; 60}; 61 62/// __libcpp_debug_function_type - The type of the assertion failure handler. 63typedef void(*__libcpp_debug_function_type)(__libcpp_debug_info const&); 64 65/// __libcpp_debug_function - The handler function called when a _LIBCPP_ASSERT 66/// fails. 67extern _LIBCPP_EXPORTED_FROM_ABI __libcpp_debug_function_type __libcpp_debug_function; 68 69/// __libcpp_abort_debug_function - A debug handler that aborts when called. 70_LIBCPP_NORETURN _LIBCPP_FUNC_VIS 71void __libcpp_abort_debug_function(__libcpp_debug_info const&); 72 73/// __libcpp_set_debug_function - Set the debug handler to the specified 74/// function. 75_LIBCPP_FUNC_VIS 76bool __libcpp_set_debug_function(__libcpp_debug_function_type __func); 77 78#if _LIBCPP_DEBUG_LEVEL == 2 || defined(_LIBCPP_BUILDING_LIBRARY) 79 80struct _LIBCPP_TYPE_VIS __c_node; 81 82struct _LIBCPP_TYPE_VIS __i_node 83{ 84 void* __i_; 85 __i_node* __next_; 86 __c_node* __c_; 87 88#ifndef _LIBCPP_CXX03_LANG 89 __i_node(const __i_node&) = delete; 90 __i_node& operator=(const __i_node&) = delete; 91#else 92private: 93 __i_node(const __i_node&); 94 __i_node& operator=(const __i_node&); 95public: 96#endif 97 _LIBCPP_INLINE_VISIBILITY 98 __i_node(void* __i, __i_node* __next, __c_node* __c) 99 : __i_(__i), __next_(__next), __c_(__c) {} 100 ~__i_node(); 101}; 102 103struct _LIBCPP_TYPE_VIS __c_node 104{ 105 void* __c_; 106 __c_node* __next_; 107 __i_node** beg_; 108 __i_node** end_; 109 __i_node** cap_; 110 111#ifndef _LIBCPP_CXX03_LANG 112 __c_node(const __c_node&) = delete; 113 __c_node& operator=(const __c_node&) = delete; 114#else 115private: 116 __c_node(const __c_node&); 117 __c_node& operator=(const __c_node&); 118public: 119#endif 120 _LIBCPP_INLINE_VISIBILITY 121 __c_node(void* __c, __c_node* __next) 122 : __c_(__c), __next_(__next), beg_(nullptr), end_(nullptr), cap_(nullptr) {} 123 virtual ~__c_node(); 124 125 virtual bool __dereferenceable(const void*) const = 0; 126 virtual bool __decrementable(const void*) const = 0; 127 virtual bool __addable(const void*, ptrdiff_t) const = 0; 128 virtual bool __subscriptable(const void*, ptrdiff_t) const = 0; 129 130 void __add(__i_node* __i); 131 _LIBCPP_HIDDEN void __remove(__i_node* __i); 132}; 133 134template <class _Cont> 135struct _C_node 136 : public __c_node 137{ 138 _C_node(void* __c, __c_node* __n) 139 : __c_node(__c, __n) {} 140 141 virtual bool __dereferenceable(const void*) const; 142 virtual bool __decrementable(const void*) const; 143 virtual bool __addable(const void*, ptrdiff_t) const; 144 virtual bool __subscriptable(const void*, ptrdiff_t) const; 145}; 146 147template <class _Cont> 148inline bool 149_C_node<_Cont>::__dereferenceable(const void* __i) const 150{ 151 typedef typename _Cont::const_iterator iterator; 152 const iterator* __j = static_cast<const iterator*>(__i); 153 _Cont* _Cp = static_cast<_Cont*>(__c_); 154 return _Cp->__dereferenceable(__j); 155} 156 157template <class _Cont> 158inline bool 159_C_node<_Cont>::__decrementable(const void* __i) const 160{ 161 typedef typename _Cont::const_iterator iterator; 162 const iterator* __j = static_cast<const iterator*>(__i); 163 _Cont* _Cp = static_cast<_Cont*>(__c_); 164 return _Cp->__decrementable(__j); 165} 166 167template <class _Cont> 168inline bool 169_C_node<_Cont>::__addable(const void* __i, ptrdiff_t __n) const 170{ 171 typedef typename _Cont::const_iterator iterator; 172 const iterator* __j = static_cast<const iterator*>(__i); 173 _Cont* _Cp = static_cast<_Cont*>(__c_); 174 return _Cp->__addable(__j, __n); 175} 176 177template <class _Cont> 178inline bool 179_C_node<_Cont>::__subscriptable(const void* __i, ptrdiff_t __n) const 180{ 181 typedef typename _Cont::const_iterator iterator; 182 const iterator* __j = static_cast<const iterator*>(__i); 183 _Cont* _Cp = static_cast<_Cont*>(__c_); 184 return _Cp->__subscriptable(__j, __n); 185} 186 187class _LIBCPP_TYPE_VIS __libcpp_db 188{ 189 __c_node** __cbeg_; 190 __c_node** __cend_; 191 size_t __csz_; 192 __i_node** __ibeg_; 193 __i_node** __iend_; 194 size_t __isz_; 195 196 __libcpp_db(); 197public: 198#ifndef _LIBCPP_CXX03_LANG 199 __libcpp_db(const __libcpp_db&) = delete; 200 __libcpp_db& operator=(const __libcpp_db&) = delete; 201#else 202private: 203 __libcpp_db(const __libcpp_db&); 204 __libcpp_db& operator=(const __libcpp_db&); 205public: 206#endif 207 ~__libcpp_db(); 208 209 class __db_c_iterator; 210 class __db_c_const_iterator; 211 class __db_i_iterator; 212 class __db_i_const_iterator; 213 214 __db_c_const_iterator __c_end() const; 215 __db_i_const_iterator __i_end() const; 216 217 typedef __c_node*(_InsertConstruct)(void*, void*, __c_node*); 218 219 template <class _Cont> 220 _LIBCPP_INLINE_VISIBILITY static __c_node* __create_C_node(void *__mem, void *__c, __c_node *__next) { 221 return ::new (__mem) _C_node<_Cont>(__c, __next); 222 } 223 224 template <class _Cont> 225 _LIBCPP_INLINE_VISIBILITY 226 void __insert_c(_Cont* __c) 227 { 228 __insert_c(static_cast<void*>(__c), &__create_C_node<_Cont>); 229 } 230 231 void __insert_i(void* __i); 232 void __insert_c(void* __c, _InsertConstruct* __fn); 233 void __erase_c(void* __c); 234 235 void __insert_ic(void* __i, const void* __c); 236 void __iterator_copy(void* __i, const void* __i0); 237 void __erase_i(void* __i); 238 239 void* __find_c_from_i(void* __i) const; 240 void __invalidate_all(void* __c); 241 __c_node* __find_c_and_lock(void* __c) const; 242 __c_node* __find_c(void* __c) const; 243 void unlock() const; 244 245 void swap(void* __c1, void* __c2); 246 247 248 bool __dereferenceable(const void* __i) const; 249 bool __decrementable(const void* __i) const; 250 bool __addable(const void* __i, ptrdiff_t __n) const; 251 bool __subscriptable(const void* __i, ptrdiff_t __n) const; 252 bool __less_than_comparable(const void* __i, const void* __j) const; 253private: 254 _LIBCPP_HIDDEN 255 __i_node* __insert_iterator(void* __i); 256 _LIBCPP_HIDDEN 257 __i_node* __find_iterator(const void* __i) const; 258 259 friend _LIBCPP_FUNC_VIS __libcpp_db* __get_db(); 260}; 261 262_LIBCPP_FUNC_VIS __libcpp_db* __get_db(); 263_LIBCPP_FUNC_VIS const __libcpp_db* __get_const_db(); 264 265 266#endif // _LIBCPP_DEBUG_LEVEL == 2 || defined(_LIBCPP_BUILDING_LIBRARY) 267 268template <class _Tp> 269_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_insert_c(_Tp* __c) { 270#if _LIBCPP_DEBUG_LEVEL == 2 271 if (!__libcpp_is_constant_evaluated()) 272 __get_db()->__insert_c(__c); 273#else 274 (void)(__c); 275#endif 276} 277 278template <class _Tp> 279_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_insert_i(_Tp* __i) { 280#if _LIBCPP_DEBUG_LEVEL == 2 281 if (!__libcpp_is_constant_evaluated()) 282 __get_db()->__insert_i(__i); 283#else 284 (void)(__i); 285#endif 286} 287 288_LIBCPP_END_NAMESPACE_STD 289 290#endif // _LIBCPP_DEBUG_H 291