diff mbox

libstdc++/66017 Avoid bad casts and fix alignment of _Rb_tree_node<long long>::_M_storage

Message ID 20150527111902.GH2985@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely May 27, 2015, 11:19 a.m. UTC
On 26/05/15 15:46 +0100, Jonathan Wakely wrote:
>On 22/05/15 18:48 +0100, Jonathan Wakely wrote:
>>On 22/05/15 16:21 +0100, Jonathan Wakely wrote:
>>>On 22/05/15 17:13 +0200, Jakub Jelinek wrote:
>>>>On Fri, May 22, 2015 at 03:59:47PM +0100, Jonathan Wakely wrote:
>>>>>>>+      alignas(alignof(_Tp2)) unsigned char _M_storage[sizeof(_Tp)];
>>>>>>
>>>>>>Is alignof(_Tp2) always the same as alignof(_Tp2::_M_t) on all targets
>>>>>>(I mean, won't some target align the structure more than its only field)?
>>>>>
>>>>>Hmm, maybe. I don't know.
>>>>>
>>>>>>Wouldn't it be safer to use alignof(_Tp2::_M_t) here?
>>>>>
>>>>>Yes.
>>>>>
>>>>>>Though, apparently that is a GNU extension, so you'd need to use __alignof__
>>>>>>instead.
>>>>>
>>>>>Yes, that's what I did in an earlier version of the patch, so I'll go
>>>>>back to that.
>>>>
>>>>Just grepped around, and e.g. on powerpc64le-linux -std=c++11 -malign-power -O2
>>>>typedef double _Tp;
>>>>struct _Tp2 { _Tp _M_t; };
>>>>extern _Tp2 tp2e;
>>>>int a = alignof(_Tp2);
>>>>int b = __alignof__(_Tp2::_M_t);
>>>>int c = alignof(_Tp);
>>>>int d = __alignof__(tp2e._M_t);
>>>>int e = alignof(_Tp2::_M_t);
>>>>
>>>>we have a = 8, b = 4, c = 8, d = 4, e = 4.
>>>
>>>OK, thanks.
>>>
>>>>Note clang++ with -pedantic-errors errors out on alignof(_Tp2::_M_t) though.
>>>
>>>It allows __alignof__ though.
>>
>>Revised patches attached, as two separate commits because the first
>>should be backported but the second doesn't need to be.
>>
>>This includes the necessary changes for the Python printers.
>
>The change to __aligned_buffer (which makes _Rb_tree_node<long long>
>consistent in c++98 and c++11 modes) also affects some other
>C++11-only types. Compiling the attached program with -std=gnu++11
>-m32 before and after the patch produces these results:
>
>Before:
>
> future<long long> shared state: alignment: 8 size: 24
> shared_ptr<long long> control block: alignment: 8 size: 24
> forward_list<long long> node: alignment: 8 size: 16
> unordered_set<long long> node: alignment: 8 size: 16
>
>After:
>
> future<long long> shared state: alignment: 4 size: 20
> shared_ptr<long long> control block: alignment: 4 size: 20
> forward_list<long long> node: alignment: 4 size: 12
> unordered_set<long long> node: alignment: 4 size: 12
>
>The fix for _Rb_tree_node<long long> is a bug fix and necessary for
>consistency with existing c++98 code, which is more important than
>consistency with existing c++11 code using 5.1 or earlier releases.
>
>But changing the other types as well would make 5.2 inconsistent with
>5.1 for those types. We could just make that change and deal with it,
>or I could keep __aligned_buffer unchanged and add a new
>__aligned_buffer_mem for use in _Rb_tree_node, so we only change the
>one type that is currently inconsistent between c++98 and c++11 modes.
>The attached patch makes that smaller change (the second patch in my
>last mail remains unchanged).
>
>It's a shame to waste some space in the other types using
>__aligned_buffer, and to have to maintain both __aligned_buffer and
>__aligned_buffer_mem, but I think this is safer.

Here's the version I've committed, it's the same as the version
yesterday but renaming __aligned_buffer_mem to __aligned_membuf and
adding some comments to <ext/aligned_buffer.h> explaining why there
are two types.

Tested powerpc64le-linux, committed to trunk.

I plan to commit patch1.txt to gcc-5-branch too.
commit 8dae241ed96d8ad400a4f8af7748a5bd0315c0e7
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu May 21 14:41:16 2015 +0100

    	PR libstdc++/66017
    	* include/bits/stl_tree.h (_Rb_tree_node): Use __aligned_membuf.
    	(_Rb_tree_iterator, _Rb_tree_const_iterator): Support construction
    	from _Base_ptr.
    	(_Rb_tree_const_iterator::_M_const_cast): Remove static_cast.
    	(_Rb_tree::begin, _Rb_tree::end): Remove static_cast.
    	* include/ext/aligned_buffer.h (__aligned_membuf): New type using
    	alignment of _Tp as a member subobject, not as a complete object.
    	* python/libstdcxx/v6/printers.py (StdRbtreeIteratorPrinter): Lookup
    	_Link_type manually as it might not be in the debug info.
commit 04bab95db326f2c1ca51f3b6f673883f50025245
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri May 22 13:54:50 2015 +0100

    	* include/bits/stl_tree.h (_Rb_tree::_M_end()): Return _Base_ptr
    	instead of downcasting.
    	(_Rb_tree::_M_copy): Change second parameter to _Base_ptr.
    	(_Rb_tree::_M_lower_bound, _Rb_tree:_M_upper_bound): Likewise.
    	(_Rb_tree::_S_iter): Remove.
    	(_Rb_tree::_S_lower_bound_tr, _Rb_tree::_S_upper_bound_tr): Remove.
    	(_Rb_tree::_M_find_tr(const _Kt&) const): Call _M_lower_bound_tr
    	instead of _S_lower_bound_tr
    	(_Rb_tree::_M_find_tr(const _Kt&)): Call const overload.
    	(_Rb_tree::_M_lower_bound_tr(const _Kt&) const): Do the search here
    	instead of calling _S_lower_bound_tr.
    	(_Rb_tree::_M_lower_bound_tr(const _Kt&)): Call const overload.
    	(_Rb_tree::_M_upper_bound_tr(const _Kt&) const): Do the search here
    	instead of calling _S_upper_bound_tr.
    	(_Rb_tree::_M_upper_bound_tr(const _Kt&)): Call const overload.
    	(_Rb_tree::_M_equal_range_tr(const _Kt&)): Likewise.
    	(_Rb_tree::equal_range): Use _Base_ptr for end pointer.
    	(_Rb_tree::_M_get_insert_unique_pos): Likewise.
    	(_Rb_tree::_M_get_insert_equal_pos): Likewise.
    	(_Rb_tree::_M_insert_equal_lower_node): Likewise.
    	(_Rb_tree::_M_insert_unique, _Rb_tree::_M_emplace_unique,
    	_Rb_tree::_M_emplace_hint_unique): Remove static_cast.

diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h
index d39042f..240f522 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -658,13 +658,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  (this->_M_impl._M_header._M_parent);
       }
 
-      _Link_type
+      _Base_ptr
       _M_end() _GLIBCXX_NOEXCEPT
-      { return reinterpret_cast<_Link_type>(&this->_M_impl._M_header); }
+      { return &this->_M_impl._M_header; }
 
-      _Const_Link_type
+      _Const_Base_ptr
       _M_end() const _GLIBCXX_NOEXCEPT
-      { return reinterpret_cast<_Const_Link_type>(&this->_M_impl._M_header); }
+      { return &this->_M_impl._M_header; }
 
       static const_reference
       _S_value(_Const_Link_type __x)
@@ -774,10 +774,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       template<typename _NodeGen>
 	_Link_type
-	_M_copy(_Const_Link_type __x, _Link_type __p, _NodeGen&);
+	_M_copy(_Const_Link_type __x, _Base_ptr __p, _NodeGen&);
 
       _Link_type
-      _M_copy(_Const_Link_type __x, _Link_type __p)
+      _M_copy(_Const_Link_type __x, _Base_ptr __p)
       {
 	_Alloc_node __an(*this);
 	return _M_copy(__x, __p, __an);
@@ -787,19 +787,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _M_erase(_Link_type __x);
 
       iterator
-      _M_lower_bound(_Link_type __x, _Link_type __y,
+      _M_lower_bound(_Link_type __x, _Base_ptr __y,
 		     const _Key& __k);
 
       const_iterator
-      _M_lower_bound(_Const_Link_type __x, _Const_Link_type __y,
+      _M_lower_bound(_Const_Link_type __x, _Const_Base_ptr __y,
 		     const _Key& __k) const;
 
       iterator
-      _M_upper_bound(_Link_type __x, _Link_type __y,
+      _M_upper_bound(_Link_type __x, _Base_ptr __y,
 		     const _Key& __k);
 
       const_iterator
-      _M_upper_bound(_Const_Link_type __x, _Const_Link_type __y,
+      _M_upper_bound(_Const_Link_type __x, _Const_Base_ptr __y,
 		     const _Key& __k) const;
 
     public:
@@ -1117,43 +1117,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	__is_transparent<_Cmp, _Kt, __void_t<typename _Cmp::is_transparent>>
 	{ typedef void type; };
 
-      static auto _S_iter(_Link_type __x) { return iterator(__x); }
-
-      static auto _S_iter(_Const_Link_type __x) { return const_iterator(__x); }
-
-      template<typename _Cmp, typename _Link, typename _Kt>
-	static auto
-	_S_lower_bound_tr(_Cmp& __cmp, _Link __x, _Link __y, const _Kt& __k)
-	{
-	  while (__x != 0)
-	    if (!__cmp(_S_key(__x), __k))
-	      __y = __x, __x = _S_left(__x);
-	    else
-	      __x = _S_right(__x);
-	  return _S_iter(__y);
-	}
-
-      template<typename _Cmp, typename _Link, typename _Kt>
-	static auto
-	_S_upper_bound_tr(_Cmp& __cmp, _Link __x, _Link __y, const _Kt& __k)
-	{
-	  while (__x != 0)
-	    if (__cmp(__k, _S_key(__x)))
-	      __y = __x, __x = _S_left(__x);
-	    else
-	      __x = _S_right(__x);
-	  return _S_iter(__y);
-	}
-
       template<typename _Kt,
 	       typename _Req = typename __is_transparent<_Compare, _Kt>::type>
 	iterator
 	_M_find_tr(const _Kt& __k)
 	{
-	  auto& __cmp = _M_impl._M_key_compare;
-	  auto __j = _S_lower_bound_tr(__cmp, _M_begin(), _M_end(), __k);
-	  return (__j == end() || __cmp(__k, _S_key(__j._M_node)))
-	    ? end() : __j;
+	  const _Rb_tree* __const_this = this;
+	  return __const_this->_M_find_tr(__k)._M_const_cast();
 	}
 
       template<typename _Kt,
@@ -1161,10 +1131,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	const_iterator
 	_M_find_tr(const _Kt& __k) const
 	{
-	  auto& __cmp = _M_impl._M_key_compare;
-	  auto __j = _S_lower_bound_tr(__cmp, _M_begin(), _M_end(), __k);
-	  return (__j == end() || __cmp(__k, _S_key(__j._M_node)))
-	    ? end() : __j;
+	  auto __j = _M_lower_bound_tr(__k);
+	  if (__j != end() && _M_impl._M_key_compare(__k, _S_key(__j._M_node)))
+	    __j = end();
+	  return __j;
 	}
 
       template<typename _Kt,
@@ -1181,8 +1151,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	iterator
 	_M_lower_bound_tr(const _Kt& __k)
 	{
-	  auto& __cmp = _M_impl._M_key_compare;
-	  return _S_lower_bound_tr(__cmp, _M_begin(), _M_end(), __k);
+	  const _Rb_tree* __const_this = this;
+	  return __const_this->_M_lower_bound_tr(__k)._M_const_cast();
 	}
 
       template<typename _Kt,
@@ -1190,8 +1160,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	const_iterator
 	_M_lower_bound_tr(const _Kt& __k) const
 	{
-	  auto& __cmp = _M_impl._M_key_compare;
-	  return _S_lower_bound_tr(__cmp, _M_begin(), _M_end(), __k);
+	  auto __x = _M_begin();
+	  auto __y = _M_end();
+	  while (__x != 0)
+	    if (!_M_impl._M_key_compare(_S_key(__x), __k))
+	      {
+		__y = __x;
+		__x = _S_left(__x);
+	      }
+	    else
+	      __x = _S_right(__x);
+	  return const_iterator(__y);
 	}
 
       template<typename _Kt,
@@ -1199,8 +1178,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	iterator
 	_M_upper_bound_tr(const _Kt& __k)
 	{
-	  auto& __cmp = _M_impl._M_key_compare;
-	  return _S_upper_bound_tr(__cmp, _M_begin(), _M_end(), __k);
+	  const _Rb_tree* __const_this = this;
+	  return __const_this->_M_upper_bound_tr(__k)._M_const_cast();
 	}
 
       template<typename _Kt,
@@ -1208,8 +1187,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	const_iterator
 	_M_upper_bound_tr(const _Kt& __k) const
 	{
-	  auto& __cmp = _M_impl._M_key_compare;
-	  return _S_upper_bound_tr(__cmp, _M_begin(), _M_end(), __k);
+	  auto __x = _M_begin();
+	  auto __y = _M_end();
+	  while (__x != 0)
+	    if (_M_impl._M_key_compare(__k, _S_key(__x)))
+	      {
+		__y = __x;
+		__x = _S_left(__x);
+	      }
+	    else
+	      __x = _S_right(__x);
+	  return const_iterator(__y);
 	}
 
       template<typename _Kt,
@@ -1217,12 +1205,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	pair<iterator, iterator>
 	_M_equal_range_tr(const _Kt& __k)
 	{
-	  auto __low = _M_lower_bound_tr(__k);
-	  auto __high = __low;
-	  auto& __cmp = _M_impl._M_key_compare;
-	  while (__high != end() && !__cmp(__k, _S_key(__high._M_node)))
-	    ++__high;
-	  return { __low, __high };
+	  const _Rb_tree* __const_this = this;
+	  auto __ret = __const_this->_M_equal_range_tr(__k);
+	  return { __ret.first._M_const_cast(), __ret.second._M_const_cast() };
 	}
 
       template<typename _Kt,
@@ -1553,7 +1538,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
     {
       _Link_type __x = _M_begin();
-      _Link_type __y = _M_end();
+      _Base_ptr __y = _M_end();
       while (__x != 0)
 	{
 	  __y = __x;
@@ -1568,7 +1553,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     template<typename _NodeGen>
       typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::_Link_type
       _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::
-      _M_copy(_Const_Link_type __x, _Link_type __p, _NodeGen& __node_gen)
+      _M_copy(_Const_Link_type __x, _Base_ptr __p, _NodeGen& __node_gen)
       {
 	// Structural copy. __x and __p must be non-null.
 	_Link_type __top = _M_clone_node(__x, __node_gen);
@@ -1621,7 +1606,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     typename _Rb_tree<_Key, _Val, _KeyOfValue,
 		      _Compare, _Alloc>::iterator
     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
-    _M_lower_bound(_Link_type __x, _Link_type __y,
+    _M_lower_bound(_Link_type __x, _Base_ptr __y,
 		   const _Key& __k)
     {
       while (__x != 0)
@@ -1637,7 +1622,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     typename _Rb_tree<_Key, _Val, _KeyOfValue,
 		      _Compare, _Alloc>::const_iterator
     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
-    _M_lower_bound(_Const_Link_type __x, _Const_Link_type __y,
+    _M_lower_bound(_Const_Link_type __x, _Const_Base_ptr __y,
 		   const _Key& __k) const
     {
       while (__x != 0)
@@ -1653,7 +1638,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     typename _Rb_tree<_Key, _Val, _KeyOfValue,
 		      _Compare, _Alloc>::iterator
     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
-    _M_upper_bound(_Link_type __x, _Link_type __y,
+    _M_upper_bound(_Link_type __x, _Base_ptr __y,
 		   const _Key& __k)
     {
       while (__x != 0)
@@ -1669,7 +1654,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     typename _Rb_tree<_Key, _Val, _KeyOfValue,
 		      _Compare, _Alloc>::const_iterator
     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
-    _M_upper_bound(_Const_Link_type __x, _Const_Link_type __y,
+    _M_upper_bound(_Const_Link_type __x, _Const_Base_ptr __y,
 		   const _Key& __k) const
     {
       while (__x != 0)
@@ -1690,7 +1675,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     equal_range(const _Key& __k)
     {
       _Link_type __x = _M_begin();
-      _Link_type __y = _M_end();
+      _Base_ptr __y = _M_end();
       while (__x != 0)
 	{
 	  if (_M_impl._M_key_compare(_S_key(__x), __k))
@@ -1699,7 +1684,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    __y = __x, __x = _S_left(__x);
 	  else
 	    {
-	      _Link_type __xu(__x), __yu(__y);
+	      _Link_type __xu(__x);
+	      _Base_ptr __yu(__y);
 	      __y = __x, __x = _S_left(__x);
 	      __xu = _S_right(__xu);
 	      return pair<iterator,
@@ -1721,7 +1707,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     equal_range(const _Key& __k) const
     {
       _Const_Link_type __x = _M_begin();
-      _Const_Link_type __y = _M_end();
+      _Const_Base_ptr __y = _M_end();
       while (__x != 0)
 	{
 	  if (_M_impl._M_key_compare(_S_key(__x), __k))
@@ -1730,7 +1716,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    __y = __x, __x = _S_left(__x);
 	  else
 	    {
-	      _Const_Link_type __xu(__x), __yu(__y);
+	      _Const_Link_type __xu(__x);
+	      _Const_Base_ptr __yu(__y);
 	      __y = __x, __x = _S_left(__x);
 	      __xu = _S_right(__xu);
 	      return pair<const_iterator,
@@ -1802,7 +1789,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       typedef pair<_Base_ptr, _Base_ptr> _Res;
       _Link_type __x = _M_begin();
-      _Link_type __y = _M_end();
+      _Base_ptr __y = _M_end();
       bool __comp = true;
       while (__x != 0)
 	{
@@ -1834,7 +1821,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       typedef pair<_Base_ptr, _Base_ptr> _Res;
       _Link_type __x = _M_begin();
-      _Link_type __y = _M_end();
+      _Base_ptr __y = _M_end();
       while (__x != 0)
 	{
 	  __y = __x;
@@ -1870,7 +1857,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		      true);
 	}
 
-      return _Res(iterator(static_cast<_Link_type>(__res.first)), false);
+      return _Res(iterator(__res.first), false);
     }
 
   template<typename _Key, typename _Val, typename _KeyOfValue,
@@ -1976,7 +1963,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	return _M_insert_(__res.first, __res.second,
 			  _GLIBCXX_FORWARD(_Arg, __v),
 			  __node_gen);
-      return iterator(static_cast<_Link_type>(__res.first));
+      return iterator(__res.first);
     }
 
   template<typename _Key, typename _Val, typename _KeyOfValue,
@@ -2102,7 +2089,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _M_insert_equal_lower_node(_Link_type __z)
     {
       _Link_type __x = _M_begin();
-      _Link_type __y = _M_end();
+      _Base_ptr __y = _M_end();
       while (__x != 0)
 	{
 	  __y = __x;
@@ -2130,7 +2117,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	      return _Res(_M_insert_node(__res.first, __res.second, __z), true);
 	
 	    _M_drop_node(__z);
-	    return _Res(iterator(static_cast<_Link_type>(__res.first)), false);
+	    return _Res(iterator(__res.first), false);
 	  }
 	__catch(...)
 	  {
@@ -2177,7 +2164,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	      return _M_insert_node(__res.first, __res.second, __z);
 
 	    _M_drop_node(__z);
-	    return iterator(static_cast<_Link_type>(__res.first));
+	    return iterator(__res.first);
 	  }
 	__catch(...)
 	  {
diff mbox

Patch

diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h
index 5ca8e28..d39042f 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -146,7 +146,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _M_valptr() const
       { return std::__addressof(_M_value_field); }
 #else
-      __gnu_cxx::__aligned_buffer<_Val> _M_storage;
+      __gnu_cxx::__aligned_membuf<_Val> _M_storage;
 
       _Val*
       _M_valptr()
@@ -188,7 +188,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _M_node() { }
 
       explicit
-      _Rb_tree_iterator(_Link_type __x) _GLIBCXX_NOEXCEPT
+      _Rb_tree_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT
       : _M_node(__x) { }
 
       reference
@@ -260,7 +260,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _M_node() { }
 
       explicit
-      _Rb_tree_const_iterator(_Link_type __x) _GLIBCXX_NOEXCEPT
+      _Rb_tree_const_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT
       : _M_node(__x) { }
 
       _Rb_tree_const_iterator(const iterator& __it) _GLIBCXX_NOEXCEPT
@@ -268,8 +268,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       iterator
       _M_const_cast() const _GLIBCXX_NOEXCEPT
-      { return iterator(static_cast<typename iterator::_Link_type>
-			(const_cast<typename iterator::_Base_ptr>(_M_node))); }
+      { return iterator(const_cast<typename iterator::_Base_ptr>(_M_node)); }
 
       reference
       operator*() const _GLIBCXX_NOEXCEPT
@@ -868,28 +867,19 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       iterator
       begin() _GLIBCXX_NOEXCEPT
-      { 
-	return iterator(static_cast<_Link_type>
-			(this->_M_impl._M_header._M_left));
-      }
+      { return iterator(this->_M_impl._M_header._M_left); }
 
       const_iterator
       begin() const _GLIBCXX_NOEXCEPT
-      { 
-	return const_iterator(static_cast<_Const_Link_type>
-			      (this->_M_impl._M_header._M_left));
-      }
+      { return const_iterator(this->_M_impl._M_header._M_left); }
 
       iterator
       end() _GLIBCXX_NOEXCEPT
-      { return iterator(static_cast<_Link_type>(&this->_M_impl._M_header)); }
+      { return iterator(&this->_M_impl._M_header); }
 
       const_iterator
       end() const _GLIBCXX_NOEXCEPT
-      { 
-	return const_iterator(static_cast<_Const_Link_type>
-			      (&this->_M_impl._M_header));
-      }
+      { return const_iterator(&this->_M_impl._M_header); }
 
       reverse_iterator
       rbegin() _GLIBCXX_NOEXCEPT
diff --git a/libstdc++-v3/include/ext/aligned_buffer.h b/libstdc++-v3/include/ext/aligned_buffer.h
index 01f5729..d023bc1 100644
--- a/libstdc++-v3/include/ext/aligned_buffer.h
+++ b/libstdc++-v3/include/ext/aligned_buffer.h
@@ -39,6 +39,47 @@ 
 
 namespace __gnu_cxx
 {
+  // A utility type containing a POD object that can hold an object of type
+  // _Tp initialized via placement new or allocator_traits::construct.
+  // Intended for use as a data member subobject, use __aligned_buffer for
+  // complete objects.
+  template<typename _Tp>
+    struct __aligned_membuf
+    {
+      // Target macro ADJUST_FIELD_ALIGN can produce different alignment for
+      // types when used as class members. __aligned_membuf is intended
+      // for use as a class member, so align the buffer as for a class member.
+      struct _Tp2 { _Tp _M_t; };
+
+      alignas(__alignof__(_Tp2::_M_t)) unsigned char _M_storage[sizeof(_Tp)];
+
+      __aligned_membuf() = default;
+
+      // Can be used to avoid value-initialization zeroing _M_storage.
+      __aligned_membuf(std::nullptr_t) { }
+
+      void*
+      _M_addr() noexcept
+      { return static_cast<void*>(&_M_storage); }
+
+      const void*
+      _M_addr() const noexcept
+      { return static_cast<const void*>(&_M_storage); }
+
+      _Tp*
+      _M_ptr() noexcept
+      { return static_cast<_Tp*>(_M_addr()); }
+
+      const _Tp*
+      _M_ptr() const noexcept
+      { return static_cast<const _Tp*>(_M_addr()); }
+    };
+
+  // Similar to __aligned_membuf but aligned for complete objects, not members.
+  // This type is used in <forward_list>, <future>, <bits/shared_ptr_base.h>
+  // and <bits/hashtable_policy.h>, but ideally they would use __aligned_membuf
+  // instead, as it has smaller size for some types on some targets.
+  // This type is still used to avoid an ABI change.
   template<typename _Tp>
     struct __aligned_buffer
     : std::aligned_storage<sizeof(_Tp), std::alignment_of<_Tp>::value>
diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index c6f96d7..2b6e409 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -456,11 +456,12 @@  class StdRbtreeIteratorPrinter:
 
     def __init__ (self, typename, val):
         self.val = val
+        valtype = self.val.type.template_argument(0).strip_typedefs()
+        nodetype = gdb.lookup_type('std::_Rb_tree_node<' + str(valtype) + '>')
+        self.link_type = nodetype.strip_typedefs().pointer()
 
     def to_string (self):
-        typename = str(self.val.type.strip_typedefs()) + '::_Link_type'
-        nodetype = gdb.lookup_type(typename).strip_typedefs()
-        node = self.val.cast(nodetype).dereference()
+        node = self.val['_M_node'].cast(self.link_type).dereference()
         return get_value_from_Rb_tree_node(node)
 
 class StdDebugIteratorPrinter: