I am starting to granularize debug-mode checks so they can be controlled more individually. The goal is for vendors to eventually be able to select which categories of checks they want embedded in their configuration of the library with more granularity. Note that this patch is a bit weird on its own because it does not touch any of the containers that implement iterator bounds checking through the __dereferenceable check of the legacy debug mode. However, I added TODOs to string and vector to change that. Differential Revision: https://reviews.llvm.org/D138033
267 lines
7.4 KiB
C++
267 lines
7.4 KiB
C++
// -*- C++ -*-
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef _LIBCPP___DEBUG
|
|
#define _LIBCPP___DEBUG
|
|
|
|
#include <__assert>
|
|
#include <__config>
|
|
#include <cstddef>
|
|
#include <type_traits>
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
|
# pragma GCC system_header
|
|
#endif
|
|
|
|
#if defined(_LIBCPP_ENABLE_DEBUG_MODE) && !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY)
|
|
# define _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY
|
|
#endif
|
|
|
|
#if defined(_LIBCPP_ENABLE_DEBUG_MODE) && !defined(_LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING)
|
|
# define _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
|
|
#endif
|
|
|
|
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
|
|
# define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(::std::__libcpp_is_constant_evaluated() || (x), m)
|
|
#else
|
|
# define _LIBCPP_DEBUG_ASSERT(x, m) ((void)0)
|
|
#endif
|
|
|
|
#if defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_BUILDING_LIBRARY)
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
struct _LIBCPP_TYPE_VIS __c_node;
|
|
|
|
struct _LIBCPP_TYPE_VIS __i_node
|
|
{
|
|
void* __i_;
|
|
__i_node* __next_;
|
|
__c_node* __c_;
|
|
|
|
__i_node(const __i_node&) = delete;
|
|
__i_node& operator=(const __i_node&) = delete;
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
__i_node(void* __i, __i_node* __next, __c_node* __c)
|
|
: __i_(__i), __next_(__next), __c_(__c) {}
|
|
~__i_node();
|
|
};
|
|
|
|
struct _LIBCPP_TYPE_VIS __c_node
|
|
{
|
|
void* __c_;
|
|
__c_node* __next_;
|
|
__i_node** beg_;
|
|
__i_node** end_;
|
|
__i_node** cap_;
|
|
|
|
__c_node(const __c_node&) = delete;
|
|
__c_node& operator=(const __c_node&) = delete;
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
explicit __c_node(void* __c, __c_node* __next)
|
|
: __c_(__c), __next_(__next), beg_(nullptr), end_(nullptr), cap_(nullptr) {}
|
|
virtual ~__c_node();
|
|
|
|
virtual bool __dereferenceable(const void*) const = 0;
|
|
virtual bool __decrementable(const void*) const = 0;
|
|
virtual bool __addable(const void*, ptrdiff_t) const = 0;
|
|
virtual bool __subscriptable(const void*, ptrdiff_t) const = 0;
|
|
|
|
void __add(__i_node* __i);
|
|
_LIBCPP_HIDDEN void __remove(__i_node* __i);
|
|
};
|
|
|
|
template <class _Cont>
|
|
struct _C_node
|
|
: public __c_node
|
|
{
|
|
explicit _C_node(void* __c, __c_node* __n)
|
|
: __c_node(__c, __n) {}
|
|
|
|
bool __dereferenceable(const void*) const override;
|
|
bool __decrementable(const void*) const override;
|
|
bool __addable(const void*, ptrdiff_t) const override;
|
|
bool __subscriptable(const void*, ptrdiff_t) const override;
|
|
};
|
|
|
|
template <class _Cont>
|
|
inline bool
|
|
_C_node<_Cont>::__dereferenceable(const void* __i) const
|
|
{
|
|
typedef typename _Cont::const_iterator iterator;
|
|
const iterator* __j = static_cast<const iterator*>(__i);
|
|
_Cont* _Cp = static_cast<_Cont*>(__c_);
|
|
return _Cp->__dereferenceable(__j);
|
|
}
|
|
|
|
template <class _Cont>
|
|
inline bool
|
|
_C_node<_Cont>::__decrementable(const void* __i) const
|
|
{
|
|
typedef typename _Cont::const_iterator iterator;
|
|
const iterator* __j = static_cast<const iterator*>(__i);
|
|
_Cont* _Cp = static_cast<_Cont*>(__c_);
|
|
return _Cp->__decrementable(__j);
|
|
}
|
|
|
|
template <class _Cont>
|
|
inline bool
|
|
_C_node<_Cont>::__addable(const void* __i, ptrdiff_t __n) const
|
|
{
|
|
typedef typename _Cont::const_iterator iterator;
|
|
const iterator* __j = static_cast<const iterator*>(__i);
|
|
_Cont* _Cp = static_cast<_Cont*>(__c_);
|
|
return _Cp->__addable(__j, __n);
|
|
}
|
|
|
|
template <class _Cont>
|
|
inline bool
|
|
_C_node<_Cont>::__subscriptable(const void* __i, ptrdiff_t __n) const
|
|
{
|
|
typedef typename _Cont::const_iterator iterator;
|
|
const iterator* __j = static_cast<const iterator*>(__i);
|
|
_Cont* _Cp = static_cast<_Cont*>(__c_);
|
|
return _Cp->__subscriptable(__j, __n);
|
|
}
|
|
|
|
class _LIBCPP_TYPE_VIS __libcpp_db
|
|
{
|
|
__c_node** __cbeg_;
|
|
__c_node** __cend_;
|
|
size_t __csz_;
|
|
__i_node** __ibeg_;
|
|
__i_node** __iend_;
|
|
size_t __isz_;
|
|
|
|
explicit __libcpp_db();
|
|
public:
|
|
__libcpp_db(const __libcpp_db&) = delete;
|
|
__libcpp_db& operator=(const __libcpp_db&) = delete;
|
|
|
|
~__libcpp_db();
|
|
|
|
class __db_c_iterator;
|
|
class __db_c_const_iterator;
|
|
class __db_i_iterator;
|
|
class __db_i_const_iterator;
|
|
|
|
__db_c_const_iterator __c_end() const;
|
|
__db_i_const_iterator __i_end() const;
|
|
|
|
typedef __c_node*(_InsertConstruct)(void*, void*, __c_node*);
|
|
|
|
template <class _Cont>
|
|
_LIBCPP_INLINE_VISIBILITY static __c_node* __create_C_node(void *__mem, void *__c, __c_node *__next) {
|
|
return ::new (__mem) _C_node<_Cont>(__c, __next);
|
|
}
|
|
|
|
template <class _Cont>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
void __insert_c(_Cont* __c)
|
|
{
|
|
__insert_c(static_cast<void*>(__c), &__create_C_node<_Cont>);
|
|
}
|
|
|
|
void __insert_i(void* __i);
|
|
void __insert_c(void* __c, _InsertConstruct* __fn);
|
|
void __erase_c(void* __c);
|
|
|
|
void __insert_ic(void* __i, const void* __c);
|
|
void __iterator_copy(void* __i, const void* __i0);
|
|
void __erase_i(void* __i);
|
|
|
|
void* __find_c_from_i(void* __i) const;
|
|
void __invalidate_all(void* __c);
|
|
__c_node* __find_c_and_lock(void* __c) const;
|
|
__c_node* __find_c(void* __c) const;
|
|
void unlock() const;
|
|
|
|
void swap(void* __c1, void* __c2);
|
|
|
|
|
|
bool __dereferenceable(const void* __i) const;
|
|
bool __decrementable(const void* __i) const;
|
|
bool __addable(const void* __i, ptrdiff_t __n) const;
|
|
bool __subscriptable(const void* __i, ptrdiff_t __n) const;
|
|
bool __less_than_comparable(const void* __i, const void* __j) const;
|
|
private:
|
|
_LIBCPP_HIDDEN
|
|
__i_node* __insert_iterator(void* __i);
|
|
_LIBCPP_HIDDEN
|
|
__i_node* __find_iterator(const void* __i) const;
|
|
|
|
friend _LIBCPP_FUNC_VIS __libcpp_db* __get_db();
|
|
};
|
|
|
|
_LIBCPP_FUNC_VIS __libcpp_db* __get_db();
|
|
_LIBCPP_FUNC_VIS const __libcpp_db* __get_const_db();
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
#endif // defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_BUILDING_LIBRARY)
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
template <class _Tp>
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_insert_c(_Tp* __c) {
|
|
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
|
|
if (!__libcpp_is_constant_evaluated())
|
|
__get_db()->__insert_c(__c);
|
|
#else
|
|
(void)(__c);
|
|
#endif
|
|
}
|
|
|
|
template <class _Tp>
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_insert_i(_Tp* __i) {
|
|
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
|
|
if (!__libcpp_is_constant_evaluated())
|
|
__get_db()->__insert_i(__i);
|
|
#else
|
|
(void)(__i);
|
|
#endif
|
|
}
|
|
|
|
template <class _Tp>
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_erase_c(_Tp* __c) {
|
|
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
|
|
if (!__libcpp_is_constant_evaluated())
|
|
__get_db()->__erase_c(__c);
|
|
#else
|
|
(void)(__c);
|
|
#endif
|
|
}
|
|
|
|
template <class _Tp>
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_swap(_Tp* __lhs, _Tp* __rhs) {
|
|
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
|
|
if (!__libcpp_is_constant_evaluated())
|
|
__get_db()->swap(__lhs, __rhs);
|
|
#else
|
|
(void)(__lhs);
|
|
(void)(__rhs);
|
|
#endif
|
|
}
|
|
|
|
template <class _Tp>
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 inline void __debug_db_invalidate_all(_Tp* __c) {
|
|
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
|
|
if (!__libcpp_is_constant_evaluated())
|
|
__get_db()->__invalidate_all(__c);
|
|
#else
|
|
(void)(__c);
|
|
#endif
|
|
}
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
#endif // _LIBCPP___DEBUG
|