Hi mclow.lists, rsmith, sam.saariste,
I'm not 100% confident in this patch yet but because of the time crunch with
the 3.6 release I'm posting it early.
The patch works by using `static_cast` on fancy class-like pointers and
`reinterpret_cast` on raw pointers. It also changes it so that when the base
node class is needed at a call site then it gets the base pointer directly
instead of the derived pointer.
I'll do more work on this and actually convince myself of its correctness.
http://reviews.llvm.org/D6974
Files:
include/__tree
include/forward_list
include/list
include/memory
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/__tree
===================================================================
--- include/__tree
+++ include/__tree
@@ -831,18 +831,24 @@
_LIBCPP_INLINE_VISIBILITY
__node_pointer __end_node() _NOEXCEPT
{
- return static_cast<__node_pointer>
- (
- pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first())
- );
+ typedef _FancyPointerCaster<__end_node_ptr, __node_pointer> _Caster;
+ return _Caster::__from_element(__pair1_.first());
}
_LIBCPP_INLINE_VISIBILITY
__node_const_pointer __end_node() const _NOEXCEPT
{
- return static_cast<__node_const_pointer>
- (
- pointer_traits<__end_node_const_ptr>::pointer_to(const_cast<__end_node_t&>(__pair1_.first()))
- );
+ typedef _FancyPointerCaster<__end_node_const_ptr, __node_const_pointer> _Caster;
+ return _Caster::__from_element(const_cast<__end_node_t&>(__pair1_.first()));
+ }
+ _LIBCPP_INLINE_VISIBILITY
+ __end_node_ptr __end_node_pointer() _NOEXCEPT
+ {
+ return pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first());
+ }
+ _LIBCPP_INLINE_VISIBILITY
+ __end_node_const_ptr __end_node_pointer() const _NOEXCEPT
+ {
+ return pointer_traits<__end_node_const_ptr>::pointer_to(const_cast<__end_node_t&>(__pair1_.first()));
}
_LIBCPP_INLINE_VISIBILITY
__node_allocator& __node_alloc() _NOEXCEPT {return __pair1_.second();}
@@ -872,10 +878,10 @@
public:
_LIBCPP_INLINE_VISIBILITY
__node_pointer __root() _NOEXCEPT
- {return static_cast<__node_pointer> (__end_node()->__left_);}
+ {return static_cast<__node_pointer> (__end_node_pointer()->__left_);}
_LIBCPP_INLINE_VISIBILITY
__node_const_pointer __root() const _NOEXCEPT
- {return static_cast<__node_const_pointer>(__end_node()->__left_);}
+ {return static_cast<__node_const_pointer>(__end_node_pointer()->__left_);}
typedef __tree_iterator<value_type, __node_pointer, difference_type> iterator;
typedef __tree_const_iterator<value_type, __node_pointer, difference_type> const_iterator;
@@ -1156,8 +1162,8 @@
{
__node_pointer __cache = __begin_node();
__begin_node() = __end_node();
- __end_node()->__left_->__parent_ = nullptr;
- __end_node()->__left_ = nullptr;
+ __end_node_pointer()->__left_->__parent_ = nullptr;
+ __end_node_pointer()->__left_ = nullptr;
size() = 0;
// __cache->__left_ == nullptr
if (__cache->__right_ != nullptr)
@@ -1310,9 +1316,9 @@
__begin_node() = __end_node();
else
{
- __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
+ __end_node_pointer()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
__t.__begin_node() = __t.__end_node();
- __t.__end_node()->__left_ = nullptr;
+ __t.__end_node_pointer()->__left_ = nullptr;
__t.size() = 0;
}
}
@@ -1329,11 +1335,11 @@
else
{
__begin_node() = __t.__begin_node();
- __end_node()->__left_ = __t.__end_node()->__left_;
- __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
+ __end_node_pointer()->__left_ = __t.__end_node_pointer()->__left_;
+ __end_node_pointer()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
size() = __t.size();
__t.__begin_node() = __t.__end_node();
- __t.__end_node()->__left_ = nullptr;
+ __t.__end_node_pointer()->__left_ = nullptr;
__t.size() = 0;
}
}
@@ -1349,7 +1355,7 @@
_NOEXCEPT_(is_nothrow_move_assignable<value_compare>::value &&
is_nothrow_move_assignable<__node_allocator>::value)
{
- destroy(static_cast<__node_pointer>(__end_node()->__left_));
+ destroy(static_cast<__node_pointer>(__end_node_pointer()->__left_));
__begin_node_ = __t.__begin_node_;
__pair1_.first() = __t.__pair1_.first();
__move_assign_alloc(__t);
@@ -1358,9 +1364,9 @@
__begin_node() = __end_node();
else
{
- __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
+ __end_node_pointer()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
__t.__begin_node() = __t.__end_node();
- __t.__end_node()->__left_ = nullptr;
+ __t.__end_node_pointer()->__left_ = nullptr;
__t.size() = 0;
}
}
@@ -1463,11 +1469,11 @@
if (size() == 0)
__begin_node() = __end_node();
else
- __end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
+ __end_node_pointer()->__left_->__parent_ = static_cast<__node_base_pointer>(__end_node());
if (__t.size() == 0)
__t.__begin_node() = __t.__end_node();
else
- __t.__end_node()->__left_->__parent_ = static_cast<__node_base_pointer>(__t.__end_node());
+ __t.__end_node_pointer()->__left_->__parent_ = static_cast<__node_base_pointer>(__t.__end_node());
}
template <class _Tp, class _Compare, class _Allocator>
@@ -1477,7 +1483,7 @@
destroy(__root());
size() = 0;
__begin_node() = __end_node();
- __end_node()->__left_ = nullptr;
+ __end_node_pointer()->__left_ = nullptr;
}
// Find lower_bound place to insert
@@ -1714,7 +1720,7 @@
__child = __new_node;
if (__begin_node()->__left_ != nullptr)
__begin_node() = static_cast<__node_pointer>(__begin_node()->__left_);
- __tree_balance_after_insert(__end_node()->__left_, __child);
+ __tree_balance_after_insert(__end_node_pointer()->__left_, __child);
++size();
}
@@ -1980,7 +1986,7 @@
__begin_node() = __r.__ptr_;
--size();
__node_allocator& __na = __node_alloc();
- __tree_remove(__end_node()->__left_,
+ __tree_remove(__end_node_pointer()->__left_,
static_cast<__node_base_pointer>(__np));
__node_traits::destroy(__na, const_cast<value_type*>(_VSTD::addressof(*__p)));
__node_traits::deallocate(__na, __np, 1);
@@ -2289,7 +2295,7 @@
__begin_node() = static_cast<__node_pointer>(__np->__parent_);
}
--size();
- __tree_remove(__end_node()->__left_,
+ __tree_remove(__end_node_pointer()->__left_,
static_cast<__node_base_pointer>(__np));
return __node_holder(__np, _Dp(__node_alloc()));
}
Index: include/forward_list
===================================================================
--- include/forward_list
+++ include/forward_list
@@ -389,12 +389,29 @@
_LIBCPP_INLINE_VISIBILITY
__node_pointer __before_begin() _NOEXCEPT
- {return static_cast<__node_pointer>(pointer_traits<__begin_node_pointer>::
- pointer_to(__before_begin_.first()));}
+ {
+ typedef _FancyPointerCaster<__begin_node_pointer, __node_pointer> _Caster;
+ return _Caster::__from_element(__before_begin_.first());
+ }
+
_LIBCPP_INLINE_VISIBILITY
__node_const_pointer __before_begin() const _NOEXCEPT
- {return static_cast<__node_const_pointer>(pointer_traits<__begin_node_pointer>::
- pointer_to(const_cast<__begin_node&>(__before_begin_.first())));}
+ {
+ typedef _FancyPointerCaster<__begin_node_pointer, __node_const_pointer> _Caster;
+ return _Caster::__from_element(const_cast<__begin_node&>(__before_begin_.first()));
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ __begin_node_pointer __before_begin_pointer() _NOEXCEPT
+ {
+ return pointer_traits<__begin_node_pointer>::pointer_to(__before_begin_.first());
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ __begin_node_pointer __before_begin_pointer() const _NOEXCEPT
+ {
+ return pointer_traits<__begin_node_pointer>::pointer_to(const_cast<__begin_node&>(__before_begin_.first()));
+ }
_LIBCPP_INLINE_VISIBILITY
__node_allocator& __alloc() _NOEXCEPT
@@ -496,7 +513,7 @@
_NOEXCEPT_(is_nothrow_move_constructible<__node_allocator>::value)
: __before_begin_(_VSTD::move(__x.__before_begin_))
{
- __x.__before_begin()->__next_ = nullptr;
+ __x.__before_begin_pointer()->__next_ = nullptr;
}
template <class _Tp, class _Alloc>
@@ -507,8 +524,8 @@
{
if (__alloc() == __x.__alloc())
{
- __before_begin()->__next_ = __x.__before_begin()->__next_;
- __x.__before_begin()->__next_ = nullptr;
+ __before_begin_pointer()->__next_ = __x.__before_begin_pointer()->__next_;
+ __x.__before_begin_pointer()->__next_ = nullptr;
}
}
@@ -529,7 +546,7 @@
{
__swap_alloc(__alloc(), __x.__alloc());
using _VSTD::swap;
- swap(__before_begin()->__next_, __x.__before_begin()->__next_);
+ swap(__before_begin_pointer()->__next_, __x.__before_begin_pointer()->__next_);
}
template <class _Tp, class _Alloc>
@@ -537,14 +554,14 @@
__forward_list_base<_Tp, _Alloc>::clear() _NOEXCEPT
{
__node_allocator& __a = __alloc();
- for (__node_pointer __p = __before_begin()->__next_; __p != nullptr;)
+ for (__node_pointer __p = __before_begin_pointer()->__next_; __p != nullptr;)
{
__node_pointer __next = __p->__next_;
__node_traits::destroy(__a, _VSTD::addressof(__p->__value_));
__node_traits::deallocate(__a, __p, 1);
__p = __next;
}
- __before_begin()->__next_ = nullptr;
+ __before_begin_pointer()->__next_ = nullptr;
}
template <class _Tp, class _Alloc = allocator<_Tp> >
@@ -552,10 +569,11 @@
: private __forward_list_base<_Tp, _Alloc>
{
typedef __forward_list_base<_Tp, _Alloc> base;
- typedef typename base::__node_allocator __node_allocator;
- typedef typename base::__node __node;
- typedef typename base::__node_traits __node_traits;
- typedef typename base::__node_pointer __node_pointer;
+ typedef typename base::__node_allocator __node_allocator;
+ typedef typename base::__node __node;
+ typedef typename base::__node_traits __node_traits;
+ typedef typename base::__node_pointer __node_pointer;
+ typedef typename base::__begin_node_pointer __begin_node_pointer;
public:
typedef _Tp value_type;
@@ -638,10 +656,10 @@
_LIBCPP_INLINE_VISIBILITY
iterator begin() _NOEXCEPT
- {return iterator(base::__before_begin()->__next_);}
+ {return iterator(base::__before_begin_pointer()->__next_);}
_LIBCPP_INLINE_VISIBILITY
const_iterator begin() const _NOEXCEPT
- {return const_iterator(base::__before_begin()->__next_);}
+ {return const_iterator(base::__before_begin_pointer()->__next_);}
_LIBCPP_INLINE_VISIBILITY
iterator end() _NOEXCEPT
{return iterator(nullptr);}
@@ -651,7 +669,7 @@
_LIBCPP_INLINE_VISIBILITY
const_iterator cbegin() const _NOEXCEPT
- {return const_iterator(base::__before_begin()->__next_);}
+ {return const_iterator(base::__before_begin_pointer()->__next_);}
_LIBCPP_INLINE_VISIBILITY
const_iterator cend() const _NOEXCEPT
{return const_iterator(nullptr);}
@@ -668,15 +686,15 @@
_LIBCPP_INLINE_VISIBILITY
bool empty() const _NOEXCEPT
- {return base::__before_begin()->__next_ == nullptr;}
+ {return base::__before_begin_pointer()->__next_ == nullptr;}
_LIBCPP_INLINE_VISIBILITY
size_type max_size() const _NOEXCEPT
{return numeric_limits<size_type>::max();}
_LIBCPP_INLINE_VISIBILITY
- reference front() {return base::__before_begin()->__next_->__value_;}
+ reference front() {return base::__before_begin_pointer()->__next_->__value_;}
_LIBCPP_INLINE_VISIBILITY
- const_reference front() const {return base::__before_begin()->__next_->__value_;}
+ const_reference front() const {return base::__before_begin_pointer()->__next_->__value_;}
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
#ifndef _LIBCPP_HAS_NO_VARIADICS
@@ -934,8 +952,8 @@
{
clear();
base::__move_assign_alloc(__x);
- base::__before_begin()->__next_ = __x.__before_begin()->__next_;
- __x.__before_begin()->__next_ = nullptr;
+ base::__before_begin_pointer()->__next_ = __x.__before_begin_pointer()->__next_;
+ __x.__before_begin_pointer()->__next_ = nullptr;
}
template <class _Tp, class _Alloc>
@@ -1039,8 +1057,8 @@
unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1));
__node_traits::construct(__a, _VSTD::addressof(__h->__value_),
_VSTD::forward<_Args>(__args)...);
- __h->__next_ = base::__before_begin()->__next_;
- base::__before_begin()->__next_ = __h.release();
+ __h->__next_ = base::__before_begin_pointer()->__next_;
+ base::__before_begin_pointer()->__next_ = __h.release();
}
#endif // _LIBCPP_HAS_NO_VARIADICS
@@ -1053,8 +1071,8 @@
typedef __allocator_destructor<__node_allocator> _Dp;
unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1));
__node_traits::construct(__a, _VSTD::addressof(__h->__value_), _VSTD::move(__v));
- __h->__next_ = base::__before_begin()->__next_;
- base::__before_begin()->__next_ = __h.release();
+ __h->__next_ = base::__before_begin_pointer()->__next_;
+ base::__before_begin_pointer()->__next_ = __h.release();
}
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
@@ -1067,8 +1085,8 @@
typedef __allocator_destructor<__node_allocator> _Dp;
unique_ptr<__node, _Dp> __h(__node_traits::allocate(__a, 1), _Dp(__a, 1));
__node_traits::construct(__a, _VSTD::addressof(__h->__value_), __v);
- __h->__next_ = base::__before_begin()->__next_;
- base::__before_begin()->__next_ = __h.release();
+ __h->__next_ = base::__before_begin_pointer()->__next_;
+ base::__before_begin_pointer()->__next_ = __h.release();
}
template <class _Tp, class _Alloc>
@@ -1076,8 +1094,8 @@
forward_list<_Tp, _Alloc>::pop_front()
{
__node_allocator& __a = base::__alloc();
- __node_pointer __p = base::__before_begin()->__next_;
- base::__before_begin()->__next_ = __p->__next_;
+ __node_pointer __p = base::__before_begin_pointer()->__next_;
+ base::__before_begin_pointer()->__next_ = __p->__next_;
__node_traits::destroy(__a, _VSTD::addressof(__p->__value_));
__node_traits::deallocate(__a, __p, 1);
}
@@ -1188,6 +1206,7 @@
forward_list<_Tp, _Alloc>::insert_after(const_iterator __p,
_InputIterator __f, _InputIterator __l)
{
+ typedef _FancyPointerCaster<__node_pointer, __begin_node_pointer> _Caster;
__node_pointer __r = __p.__ptr_;
if (__f != __l)
{
@@ -1221,8 +1240,8 @@
throw;
}
#endif // _LIBCPP_NO_EXCEPTIONS
- __last->__next_ = __r->__next_;
- __r->__next_ = __first;
+ __last->__next_ = _Caster::__from_pointer(__r)->__next_;
+ _Caster::__from_pointer(__r)->__next_ = __first;
__r = __last;
}
return iterator(__r);
@@ -1344,8 +1363,8 @@
++__lm1;
__lm1.__ptr_->__next_ = __p.__ptr_->__next_;
}
- __p.__ptr_->__next_ = __x.__before_begin()->__next_;
- __x.__before_begin()->__next_ = nullptr;
+ __p.__ptr_->__next_ = __x.__before_begin_pointer()->__next_;
+ __x.__before_begin_pointer()->__next_ = nullptr;
}
}
@@ -1486,10 +1505,10 @@
{
if (this != &__x)
{
- base::__before_begin()->__next_ = __merge(base::__before_begin()->__next_,
- __x.__before_begin()->__next_,
+ base::__before_begin_pointer()->__next_ = __merge(base::__before_begin_pointer()->__next_,
+ __x.__before_begin_pointer()->__next_,
__comp);
- __x.__before_begin()->__next_ = nullptr;
+ __x.__before_begin_pointer()->__next_ = nullptr;
}
}
@@ -1544,7 +1563,7 @@
void
forward_list<_Tp, _Alloc>::sort(_Compare __comp)
{
- base::__before_begin()->__next_ = __sort(base::__before_begin()->__next_,
+ base::__before_begin_pointer()->__next_ = __sort(base::__before_begin_pointer()->__next_,
_VSTD::distance(begin(), end()), __comp);
}
@@ -1582,7 +1601,7 @@
void
forward_list<_Tp, _Alloc>::reverse() _NOEXCEPT
{
- __node_pointer __p = base::__before_begin()->__next_;
+ __node_pointer __p = base::__before_begin_pointer()->__next_;
if (__p != nullptr)
{
__node_pointer __f = __p->__next_;
@@ -1594,7 +1613,7 @@
__p = __f;
__f = __t;
}
- base::__before_begin()->__next_ = __p;
+ base::__before_begin_pointer()->__next_ = __p;
}
}
Index: include/list
===================================================================
--- include/list
+++ include/list
@@ -215,7 +215,8 @@
_LIBCPP_INLINE_VISIBILITY
pointer __self()
{
- return static_cast<pointer>(pointer_traits<__base_pointer>::pointer_to(*this));
+ typedef _FancyPointerCaster<__base_pointer, pointer> _Caster;
+ return _Caster::__from_element(*this);
}
};
@@ -584,23 +585,21 @@
_LIBCPP_INLINE_VISIBILITY
iterator end() _NOEXCEPT
{
+ typedef _FancyPointerCaster<__node_base_pointer, __node_pointer> _Caster;
#if _LIBCPP_DEBUG_LEVEL >= 2
- return iterator(static_cast<__node_pointer>(
- pointer_traits<__node_base_pointer>::pointer_to(__end_)), this);
+ return iterator(_Caster::__from_element(__end_), this);
#else
- return iterator(static_cast<__node_pointer>(
- pointer_traits<__node_base_pointer>::pointer_to(__end_)));
+ return iterator(_Caster::__from_element(__end_));
#endif
}
_LIBCPP_INLINE_VISIBILITY
const_iterator end() const _NOEXCEPT
{
+ typedef _FancyPointerCaster<__node_base_pointer, __node_const_pointer> _Caster;
#if _LIBCPP_DEBUG_LEVEL >= 2
- return const_iterator(static_cast<__node_const_pointer>(
- pointer_traits<__node_base_pointer>::pointer_to(const_cast<__node_base&>(__end_))), this);
+ return const_iterator(_Caster::__from_element(const_cast<__node_base&>(__end_)), this);
#else
- return const_iterator(static_cast<__node_const_pointer>(
- pointer_traits<__node_base_pointer>::pointer_to(const_cast<__node_base&>(__end_))));
+ return const_iterator(_Caster::__from_element(const_cast<__node_base&>(__end_)));
#endif
}
Index: include/memory
===================================================================
--- include/memory
+++ include/memory
@@ -5438,6 +5438,48 @@
_LIBCPP_FUNC_VIS void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space);
+
+
+template <class _From, class _To>
+struct _FancyPointerCaster
+{
+ typedef pointer_traits<_From> _FromPtrTraits;
+ typedef typename _FromPtrTraits::element_type _Element;
+
+ _LIBCPP_INLINE_VISIBILITY
+ static _To __from_element(_Element & __e)
+ {
+ return static_cast<_To>(_FromPtrTraits::pointer_to(__e));
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ static _To __from_pointer(_From & __f)
+ {
+ return static_cast<_To>(__f);
+ }
+};
+
+template <class _From, class _To>
+struct _FancyPointerCaster<_From*, _To>
+{
+ typedef pointer_traits<_From*> _FromPtrTraits;
+ typedef typename _FromPtrTraits::element_type _Element;
+
+ _LIBCPP_INLINE_VISIBILITY
+ static _To __from_element(_Element & __e)
+ {
+ return reinterpret_cast<_To>(_FromPtrTraits::pointer_to(__e));
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ static _To __from_pointer(_From * __f)
+ {
+ return reinterpret_cast<_To>(__f);
+ }
+};
+
+
+
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_MEMORY
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits