1f554add5SHoward Hinnant// -*- C++ -*-
2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===//
3f554add5SHoward Hinnant//
457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7f554add5SHoward Hinnant//
8f554add5SHoward Hinnant//===----------------------------------------------------------------------===//
9f554add5SHoward Hinnant
10cc82a1b0SLouis Dionne#ifndef _LIBCPP___DEBUG
11cc82a1b0SLouis Dionne#define _LIBCPP___DEBUG
12f554add5SHoward Hinnant
13f87aa19bSLouis Dionne#include <__assert>
14c1bd9197SEric Fiselier#include <__config>
15e3cf7050SNikolas Klauser#include <type_traits>
16c1bd9197SEric Fiselier
17fc88dbd2SHoward Hinnant#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
18fc88dbd2SHoward Hinnant#  pragma GCC system_header
19fc88dbd2SHoward Hinnant#endif
20fc88dbd2SHoward Hinnant
21*f3966eafSLouis Dionne// Catch invalid uses of the legacy _LIBCPP_DEBUG toggle.
22*f3966eafSLouis Dionne#if defined(_LIBCPP_DEBUG) && _LIBCPP_DEBUG != 0 && !defined(_LIBCPP_ENABLE_DEBUG_MODE)
23*f3966eafSLouis Dionne#   error "Enabling the debug mode now requires having configured the library with support for the debug mode"
24*f3966eafSLouis Dionne#endif
25*f3966eafSLouis Dionne
26*f3966eafSLouis Dionne#if defined(_LIBCPP_ENABLE_DEBUG_MODE) && !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY)
27*f3966eafSLouis Dionne# define _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY
28*f3966eafSLouis Dionne#endif
29*f3966eafSLouis Dionne
30*f3966eafSLouis Dionne// TODO: Define this as a function instead
31*f3966eafSLouis Dionne#if defined(_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY)
32*f3966eafSLouis Dionne# if defined(_LIBCPP_CXX03_LANG)
33*f3966eafSLouis Dionne#   error Support for unspecified stability is only for C++11 and higher
34*f3966eafSLouis Dionne# endif
35*f3966eafSLouis Dionne# define _LIBCPP_DEBUG_RANDOMIZE_RANGE(__first, __last)                                                         \
36*f3966eafSLouis Dionne    do {                                                                                                        \
37*f3966eafSLouis Dionne      if (!__builtin_is_constant_evaluated())                                                                   \
38*f3966eafSLouis Dionne        std::shuffle(__first, __last, __libcpp_debug_randomizer());                                             \
39*f3966eafSLouis Dionne    } while (false)
40*f3966eafSLouis Dionne#else
41*f3966eafSLouis Dionne# define _LIBCPP_DEBUG_RANDOMIZE_RANGE(__first, __last)                                                         \
42*f3966eafSLouis Dionne    do {                                                                                                        \
43*f3966eafSLouis Dionne    } while (false)
44*f3966eafSLouis Dionne#endif
45*f3966eafSLouis Dionne
46*f3966eafSLouis Dionne#ifdef _LIBCPP_ENABLE_DEBUG_MODE
47*f3966eafSLouis Dionne#   define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(::std::__libcpp_is_constant_evaluated() || (x), m)
48*f3966eafSLouis Dionne#else
49*f3966eafSLouis Dionne#   define _LIBCPP_DEBUG_ASSERT(x, m) ((void)0)
50*f3966eafSLouis Dionne#endif
51*f3966eafSLouis Dionne
52*f3966eafSLouis Dionne#if defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_BUILDING_LIBRARY)
53*f3966eafSLouis Dionne
54f554add5SHoward Hinnant#include <cstddef>
5542185ad8SArthur O'Dwyer#include <cstdio>
5642185ad8SArthur O'Dwyer#include <cstdlib>
5731e82037SLouis Dionne
58f554add5SHoward Hinnant_LIBCPP_BEGIN_NAMESPACE_STD
59f554add5SHoward Hinnant
606e41256fSHoward Hinnantstruct _LIBCPP_TYPE_VIS __c_node;
61f554add5SHoward Hinnant
626e41256fSHoward Hinnantstruct _LIBCPP_TYPE_VIS __i_node
63f554add5SHoward Hinnant{
64f554add5SHoward Hinnant    void* __i_;
65f554add5SHoward Hinnant    __i_node* __next_;
66f554add5SHoward Hinnant    __c_node* __c_;
67f554add5SHoward Hinnant
68f554add5SHoward Hinnant    __i_node(const __i_node&) = delete;
69f554add5SHoward Hinnant    __i_node& operator=(const __i_node&) = delete;
70318507edSNikolas Klauser
71f554add5SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
72f554add5SHoward Hinnant    __i_node(void* __i, __i_node* __next, __c_node* __c)
73f554add5SHoward Hinnant        : __i_(__i), __next_(__next), __c_(__c) {}
74f554add5SHoward Hinnant    ~__i_node();
75f554add5SHoward Hinnant};
76f554add5SHoward Hinnant
776e41256fSHoward Hinnantstruct _LIBCPP_TYPE_VIS __c_node
78f554add5SHoward Hinnant{
79f554add5SHoward Hinnant    void* __c_;
80f554add5SHoward Hinnant    __c_node* __next_;
81f554add5SHoward Hinnant    __i_node** beg_;
82f554add5SHoward Hinnant    __i_node** end_;
83f554add5SHoward Hinnant    __i_node** cap_;
84f554add5SHoward Hinnant
85f554add5SHoward Hinnant    __c_node(const __c_node&) = delete;
86f554add5SHoward Hinnant    __c_node& operator=(const __c_node&) = delete;
87318507edSNikolas Klauser
88f554add5SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
89f86c2b6fSArthur O'Dwyer    explicit __c_node(void* __c, __c_node* __next)
90f554add5SHoward Hinnant        : __c_(__c), __next_(__next), beg_(nullptr), end_(nullptr), cap_(nullptr) {}
91f554add5SHoward Hinnant    virtual ~__c_node();
92f554add5SHoward Hinnant
93f554add5SHoward Hinnant    virtual bool __dereferenceable(const void*) const = 0;
94f554add5SHoward Hinnant    virtual bool __decrementable(const void*) const = 0;
95f554add5SHoward Hinnant    virtual bool __addable(const void*, ptrdiff_t) const = 0;
96f554add5SHoward Hinnant    virtual bool __subscriptable(const void*, ptrdiff_t) const = 0;
97f554add5SHoward Hinnant
98920b56caSHoward Hinnant    void __add(__i_node* __i);
99f554add5SHoward Hinnant    _LIBCPP_HIDDEN void __remove(__i_node* __i);
100f554add5SHoward Hinnant};
101f554add5SHoward Hinnant
102f554add5SHoward Hinnanttemplate <class _Cont>
103f554add5SHoward Hinnantstruct _C_node
104f554add5SHoward Hinnant    : public __c_node
105f554add5SHoward Hinnant{
106f86c2b6fSArthur O'Dwyer    explicit _C_node(void* __c, __c_node* __n)
107f554add5SHoward Hinnant        : __c_node(__c, __n) {}
108f554add5SHoward Hinnant
109f554add5SHoward Hinnant    virtual bool __dereferenceable(const void*) const;
110f554add5SHoward Hinnant    virtual bool __decrementable(const void*) const;
111f554add5SHoward Hinnant    virtual bool __addable(const void*, ptrdiff_t) const;
112f554add5SHoward Hinnant    virtual bool __subscriptable(const void*, ptrdiff_t) const;
113f554add5SHoward Hinnant};
114f554add5SHoward Hinnant
115f554add5SHoward Hinnanttemplate <class _Cont>
116687d3213SEric Fiselierinline bool
117f554add5SHoward Hinnant_C_node<_Cont>::__dereferenceable(const void* __i) const
118f554add5SHoward Hinnant{
119f554add5SHoward Hinnant    typedef typename _Cont::const_iterator iterator;
120f554add5SHoward Hinnant    const iterator* __j = static_cast<const iterator*>(__i);
121c003db1fSHoward Hinnant    _Cont* _Cp = static_cast<_Cont*>(__c_);
122c003db1fSHoward Hinnant    return _Cp->__dereferenceable(__j);
123f554add5SHoward Hinnant}
124f554add5SHoward Hinnant
125f554add5SHoward Hinnanttemplate <class _Cont>
126687d3213SEric Fiselierinline bool
127f554add5SHoward Hinnant_C_node<_Cont>::__decrementable(const void* __i) const
128f554add5SHoward Hinnant{
129f554add5SHoward Hinnant    typedef typename _Cont::const_iterator iterator;
130f554add5SHoward Hinnant    const iterator* __j = static_cast<const iterator*>(__i);
131c003db1fSHoward Hinnant    _Cont* _Cp = static_cast<_Cont*>(__c_);
132c003db1fSHoward Hinnant    return _Cp->__decrementable(__j);
133f554add5SHoward Hinnant}
134f554add5SHoward Hinnant
135f554add5SHoward Hinnanttemplate <class _Cont>
136687d3213SEric Fiselierinline bool
137f554add5SHoward Hinnant_C_node<_Cont>::__addable(const void* __i, ptrdiff_t __n) const
138f554add5SHoward Hinnant{
139f554add5SHoward Hinnant    typedef typename _Cont::const_iterator iterator;
140f554add5SHoward Hinnant    const iterator* __j = static_cast<const iterator*>(__i);
141c003db1fSHoward Hinnant    _Cont* _Cp = static_cast<_Cont*>(__c_);
142c003db1fSHoward Hinnant    return _Cp->__addable(__j, __n);
143f554add5SHoward Hinnant}
144f554add5SHoward Hinnant
145f554add5SHoward Hinnanttemplate <class _Cont>
146687d3213SEric Fiselierinline bool
147f554add5SHoward Hinnant_C_node<_Cont>::__subscriptable(const void* __i, ptrdiff_t __n) const
148f554add5SHoward Hinnant{
149f554add5SHoward Hinnant    typedef typename _Cont::const_iterator iterator;
150f554add5SHoward Hinnant    const iterator* __j = static_cast<const iterator*>(__i);
151c003db1fSHoward Hinnant    _Cont* _Cp = static_cast<_Cont*>(__c_);
152c003db1fSHoward Hinnant    return _Cp->__subscriptable(__j, __n);
153f554add5SHoward Hinnant}
154f554add5SHoward Hinnant
1556e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS __libcpp_db
156f554add5SHoward Hinnant{
157f554add5SHoward Hinnant    __c_node** __cbeg_;
158f554add5SHoward Hinnant    __c_node** __cend_;
159f554add5SHoward Hinnant    size_t   __csz_;
160f554add5SHoward Hinnant    __i_node** __ibeg_;
161f554add5SHoward Hinnant    __i_node** __iend_;
162f554add5SHoward Hinnant    size_t   __isz_;
163f554add5SHoward Hinnant
164f86c2b6fSArthur O'Dwyer    explicit __libcpp_db();
165f554add5SHoward Hinnantpublic:
166f554add5SHoward Hinnant    __libcpp_db(const __libcpp_db&) = delete;
167f554add5SHoward Hinnant    __libcpp_db& operator=(const __libcpp_db&) = delete;
168318507edSNikolas Klauser
169f554add5SHoward Hinnant    ~__libcpp_db();
170f554add5SHoward Hinnant
171f554add5SHoward Hinnant    class __db_c_iterator;
172f554add5SHoward Hinnant    class __db_c_const_iterator;
173f554add5SHoward Hinnant    class __db_i_iterator;
174f554add5SHoward Hinnant    class __db_i_const_iterator;
175f554add5SHoward Hinnant
176f554add5SHoward Hinnant    __db_c_const_iterator __c_end() const;
177f554add5SHoward Hinnant    __db_i_const_iterator __i_end() const;
178f554add5SHoward Hinnant
1791c014d75SEric Fiselier    typedef __c_node*(_InsertConstruct)(void*, void*, __c_node*);
1801c014d75SEric Fiselier
1811c014d75SEric Fiselier    template <class _Cont>
1821c014d75SEric Fiselier    _LIBCPP_INLINE_VISIBILITY static __c_node* __create_C_node(void *__mem, void *__c, __c_node *__next) {
1831c014d75SEric Fiselier        return ::new (__mem) _C_node<_Cont>(__c, __next);
1841c014d75SEric Fiselier    }
1851c014d75SEric Fiselier
186f554add5SHoward Hinnant    template <class _Cont>
187f554add5SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY
188f554add5SHoward Hinnant    void __insert_c(_Cont* __c)
189f554add5SHoward Hinnant    {
1901c014d75SEric Fiselier        __insert_c(static_cast<void*>(__c), &__create_C_node<_Cont>);
191f554add5SHoward Hinnant    }
192f554add5SHoward Hinnant
193c36bfc49SHoward Hinnant    void __insert_i(void* __i);
1941c014d75SEric Fiselier    void __insert_c(void* __c, _InsertConstruct* __fn);
195f554add5SHoward Hinnant    void __erase_c(void* __c);
196f554add5SHoward Hinnant
197f554add5SHoward Hinnant    void __insert_ic(void* __i, const void* __c);
198f554add5SHoward Hinnant    void __iterator_copy(void* __i, const void* __i0);
199f554add5SHoward Hinnant    void __erase_i(void* __i);
200f554add5SHoward Hinnant
201f554add5SHoward Hinnant    void* __find_c_from_i(void* __i) const;
202f554add5SHoward Hinnant    void __invalidate_all(void* __c);
203f554add5SHoward Hinnant    __c_node* __find_c_and_lock(void* __c) const;
204920b56caSHoward Hinnant    __c_node* __find_c(void* __c) const;
205f554add5SHoward Hinnant    void unlock() const;
206f554add5SHoward Hinnant
207f554add5SHoward Hinnant    void swap(void* __c1, void* __c2);
208f554add5SHoward Hinnant
209f554add5SHoward Hinnant
210f554add5SHoward Hinnant    bool __dereferenceable(const void* __i) const;
211f554add5SHoward Hinnant    bool __decrementable(const void* __i) const;
212f554add5SHoward Hinnant    bool __addable(const void* __i, ptrdiff_t __n) const;
213f554add5SHoward Hinnant    bool __subscriptable(const void* __i, ptrdiff_t __n) const;
21442a3046eSHoward Hinnant    bool __less_than_comparable(const void* __i, const void* __j) const;
215f554add5SHoward Hinnantprivate:
216f554add5SHoward Hinnant    _LIBCPP_HIDDEN
217f554add5SHoward Hinnant    __i_node* __insert_iterator(void* __i);
218f554add5SHoward Hinnant    _LIBCPP_HIDDEN
219f554add5SHoward Hinnant    __i_node* __find_iterator(const void* __i) const;
220f554add5SHoward Hinnant
2216e41256fSHoward Hinnant    friend _LIBCPP_FUNC_VIS __libcpp_db* __get_db();
222f554add5SHoward Hinnant};
223f554add5SHoward Hinnant
2246e41256fSHoward Hinnant_LIBCPP_FUNC_VIS __libcpp_db* __get_db();
2256e41256fSHoward Hinnant_LIBCPP_FUNC_VIS const __libcpp_db* __get_const_db();
226f554add5SHoward Hinnant
227*f3966eafSLouis Dionne_LIBCPP_END_NAMESPACE_STD
228f554add5SHoward Hinnant
229*f3966eafSLouis Dionne#endif // defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_BUILDING_LIBRARY)
230*f3966eafSLouis Dionne
231*f3966eafSLouis Dionne_LIBCPP_BEGIN_NAMESPACE_STD
232f554add5SHoward Hinnant
233e3cf7050SNikolas Klausertemplate <class _Tp>
234e3cf7050SNikolas Klauser_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_insert_c(_Tp* __c) {
235*f3966eafSLouis Dionne#ifdef _LIBCPP_ENABLE_DEBUG_MODE
236e3cf7050SNikolas Klauser    if (!__libcpp_is_constant_evaluated())
237e3cf7050SNikolas Klauser        __get_db()->__insert_c(__c);
238e3cf7050SNikolas Klauser#else
239e3cf7050SNikolas Klauser    (void)(__c);
240e3cf7050SNikolas Klauser#endif
241e3cf7050SNikolas Klauser}
242e3cf7050SNikolas Klauser
243caf5548cSNikolas Klausertemplate <class _Tp>
244caf5548cSNikolas Klauser_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_insert_i(_Tp* __i) {
245*f3966eafSLouis Dionne#ifdef _LIBCPP_ENABLE_DEBUG_MODE
246caf5548cSNikolas Klauser    if (!__libcpp_is_constant_evaluated())
247caf5548cSNikolas Klauser        __get_db()->__insert_i(__i);
248caf5548cSNikolas Klauser#else
249caf5548cSNikolas Klauser    (void)(__i);
250caf5548cSNikolas Klauser#endif
251caf5548cSNikolas Klauser}
252caf5548cSNikolas Klauser
25308f68dfeSNikolas Klausertemplate <class _Tp>
25408f68dfeSNikolas Klauser_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_erase_c(_Tp* __c) {
255*f3966eafSLouis Dionne#ifdef _LIBCPP_ENABLE_DEBUG_MODE
25608f68dfeSNikolas Klauser    if (!__libcpp_is_constant_evaluated())
25708f68dfeSNikolas Klauser        __get_db()->__erase_c(__c);
25808f68dfeSNikolas Klauser#else
25908f68dfeSNikolas Klauser    (void)(__c);
26008f68dfeSNikolas Klauser#endif
26108f68dfeSNikolas Klauser}
26208f68dfeSNikolas Klauser
26308f68dfeSNikolas Klausertemplate <class _Tp>
26408f68dfeSNikolas Klauser_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_swap(_Tp* __lhs, _Tp* __rhs) {
265*f3966eafSLouis Dionne#ifdef _LIBCPP_ENABLE_DEBUG_MODE
26608f68dfeSNikolas Klauser    if (!__libcpp_is_constant_evaluated())
26708f68dfeSNikolas Klauser        __get_db()->swap(__lhs, __rhs);
26808f68dfeSNikolas Klauser#else
26908f68dfeSNikolas Klauser    (void)(__lhs);
27008f68dfeSNikolas Klauser    (void)(__rhs);
27108f68dfeSNikolas Klauser#endif
27208f68dfeSNikolas Klauser}
27308f68dfeSNikolas Klauser
27408f68dfeSNikolas Klausertemplate <class _Tp>
27508f68dfeSNikolas Klauser_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 inline void __debug_db_invalidate_all(_Tp* __c) {
276*f3966eafSLouis Dionne#ifdef _LIBCPP_ENABLE_DEBUG_MODE
27708f68dfeSNikolas Klauser    if (!__libcpp_is_constant_evaluated())
27808f68dfeSNikolas Klauser        __get_db()->__invalidate_all(__c);
27908f68dfeSNikolas Klauser#else
28008f68dfeSNikolas Klauser    (void)(__c);
28108f68dfeSNikolas Klauser#endif
28208f68dfeSNikolas Klauser}
28308f68dfeSNikolas Klauser
284687d3213SEric Fiselier_LIBCPP_END_NAMESPACE_STD
285cec9af9eSHoward Hinnant
286cc82a1b0SLouis Dionne#endif // _LIBCPP___DEBUG
287