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

Reply via email to