Allow deque to handle incomplete types.

Allow deque and deque::iterator instantiation with incomplete element
type. This is an ABI breaking change, and it is only enabled if
LIBCXX_ABI_VERSION >= 2 or LIBCXX_ABI_UNSTABLE=ON.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@252350 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evgeniy Stepanov 2015-11-06 22:02:29 +00:00
parent 38e7a30143
commit 746572b91d
3 changed files with 77 additions and 12 deletions

View File

@ -34,7 +34,11 @@
#endif
#if defined(_LIBCPP_ABI_UNSTABLE) || _LIBCPP_ABI_VERSION >= 2
// Change short string represention so that string data starts at offset 0,
// improving its alignment in some cases.
#define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
// Fix deque iterator type in order to support incomplete types.
#define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE
#endif
#define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y

View File

@ -261,8 +261,21 @@ move_backward(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f,
__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __l,
__deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r);
template <class _ValueType, class _DiffType>
struct __deque_block_size {
static const _DiffType value = sizeof(_ValueType) < 256 ? 4096 / sizeof(_ValueType) : 16;
};
template <class _ValueType, class _Pointer, class _Reference, class _MapPointer,
class _DiffType, _DiffType _BlockSize>
class _DiffType, _DiffType _BS =
#ifdef _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE
// Keep template parameter to avoid changing all template declarations thoughout
// this file.
0
#else
__deque_block_size<_ValueType, _DiffType>::value
#endif
>
class _LIBCPP_TYPE_VIS_ONLY __deque_iterator
{
typedef _MapPointer __map_iterator;
@ -273,7 +286,7 @@ private:
__map_iterator __m_iter_;
pointer __ptr_;
static const difference_type __block_size = _BlockSize;
static const difference_type __block_size;
public:
typedef _ValueType value_type;
typedef random_access_iterator_tag iterator_category;
@ -287,7 +300,7 @@ public:
template <class _Pp, class _Rp, class _MP>
_LIBCPP_INLINE_VISIBILITY
__deque_iterator(const __deque_iterator<value_type, _Pp, _Rp, _MP, difference_type, __block_size>& __it,
__deque_iterator(const __deque_iterator<value_type, _Pp, _Rp, _MP, difference_type, _BS>& __it,
typename enable_if<is_convertible<_Pp, pointer>::value>::type* = 0) _NOEXCEPT
: __m_iter_(__it.__m_iter_), __ptr_(__it.__ptr_) {}
@ -520,6 +533,12 @@ private:
__deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2> __r);
};
template <class _ValueType, class _Pointer, class _Reference, class _MapPointer,
class _DiffType, _DiffType _BlockSize>
const _DiffType __deque_iterator<_ValueType, _Pointer, _Reference, _MapPointer,
_DiffType, _BlockSize>::__block_size =
__deque_block_size<_ValueType, _DiffType>::value;
// copy
template <class _RAIter,
@ -532,10 +551,11 @@ copy(_RAIter __f,
{
typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::difference_type difference_type;
typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::pointer pointer;
const difference_type __block_size = __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::__block_size;
while (__f != __l)
{
pointer __rb = __r.__ptr_;
pointer __re = *__r.__m_iter_ + _B2;
pointer __re = *__r.__m_iter_ + __block_size;
difference_type __bs = __re - __rb;
difference_type __n = __l - __f;
_RAIter __m = __l;
@ -560,11 +580,12 @@ copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f,
{
typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type;
typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer;
const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size;
difference_type __n = __l - __f;
while (__n > 0)
{
pointer __fb = __f.__ptr_;
pointer __fe = *__f.__m_iter_ + _B1;
pointer __fe = *__f.__m_iter_ + __block_size;
difference_type __bs = __fe - __fb;
if (__bs > __n)
{
@ -587,11 +608,12 @@ copy(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f,
{
typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type;
typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer;
const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size;
difference_type __n = __l - __f;
while (__n > 0)
{
pointer __fb = __f.__ptr_;
pointer __fe = *__f.__m_iter_ + _B1;
pointer __fe = *__f.__m_iter_ + __block_size;
difference_type __bs = __fe - __fb;
if (__bs > __n)
{
@ -705,10 +727,11 @@ move(_RAIter __f,
{
typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::difference_type difference_type;
typedef typename __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::pointer pointer;
const difference_type __block_size = __deque_iterator<_V2, _P2, _R2, _M2, _D2, _B2>::__block_size;
while (__f != __l)
{
pointer __rb = __r.__ptr_;
pointer __re = *__r.__m_iter_ + _B2;
pointer __re = *__r.__m_iter_ + __block_size;
difference_type __bs = __re - __rb;
difference_type __n = __l - __f;
_RAIter __m = __l;
@ -733,11 +756,12 @@ move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f,
{
typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type;
typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer;
const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size;
difference_type __n = __l - __f;
while (__n > 0)
{
pointer __fb = __f.__ptr_;
pointer __fe = *__f.__m_iter_ + _B1;
pointer __fe = *__f.__m_iter_ + __block_size;
difference_type __bs = __fe - __fb;
if (__bs > __n)
{
@ -760,11 +784,12 @@ move(__deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1> __f,
{
typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::difference_type difference_type;
typedef typename __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::pointer pointer;
const difference_type __block_size = __deque_iterator<_V1, _P1, _R1, _M1, _D1, _B1>::__block_size;
difference_type __n = __l - __f;
while (__n > 0)
{
pointer __fb = __f.__ptr_;
pointer __fe = *__f.__m_iter_ + _B1;
pointer __fe = *__f.__m_iter_ + __block_size;
difference_type __bs = __fe - __fb;
if (__bs > __n)
{
@ -909,7 +934,7 @@ protected:
typedef typename __alloc_traits::pointer pointer;
typedef typename __alloc_traits::const_pointer const_pointer;
static const difference_type __block_size = sizeof(value_type) < 256 ? 4096 / sizeof(value_type) : 16;
static const difference_type __block_size;
typedef typename __rebind_alloc_helper<__alloc_traits, pointer>::type __pointer_allocator;
typedef allocator_traits<__pointer_allocator> __map_traits;
@ -919,9 +944,9 @@ protected:
typedef __split_buffer<pointer, __pointer_allocator> __map;
typedef __deque_iterator<value_type, pointer, reference, __map_pointer,
difference_type, __block_size> iterator;
difference_type> iterator;
typedef __deque_iterator<value_type, const_pointer, const_reference, __map_const_pointer,
difference_type, __block_size> const_iterator;
difference_type> const_iterator;
__map __map_;
size_type __start_;
@ -996,6 +1021,11 @@ private:
{}
};
template <class _Tp, class _Allocator>
const typename __deque_base<_Tp, _Allocator>::difference_type
__deque_base<_Tp, _Allocator>::__block_size =
__deque_block_size<value_type, difference_type>::value;
template <class _Tp, class _Allocator>
bool
__deque_base<_Tp, _Allocator>::__invariants() const

View File

@ -0,0 +1,31 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <deque>
// deque()
// deque::iterator()
#define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE
#include <deque>
#include <cassert>
struct A {
std::deque<A> d;
std::deque<A>::iterator it;
std::deque<A>::reverse_iterator it2;
};
int main()
{
A a;
assert(a.d.size() == 0);
a.it = a.d.begin();
a.it2 = a.d.rend();
}