diff mbox

PR libstdc++/58729 - tr2::dynamic_bitset::resize fails

Message ID 525F8C10.6040406@verizon.net
State New
Headers show

Commit Message

Ed Smith-Rowland Oct. 17, 2013, 7:04 a.m. UTC
This patch bootstraps and tests clean on x86-64-linux.

Truthfully, dynamic_bitset needs some more love wrt C++11 and a testsuite.
It got put in before it was baked really.
That will be later.
2013-10-16  Edward Smith-Rowland  <3dw4rd@verizon.net>

	PR libstdc++/58729
	* include/tr2/dynamic_bitset (_M_resize, resize): Use input value
	to set bits; (_M_do_left_shift, _M_do_right_shift, _M_do_to_ulong,
	_M_do_to_ullong, _M_do_find_first, _M_do_find_next, _M_copy_from_ptr,
	operator>>): Move long methods outline to...
	* include/tr2/dynamic_bitset.tcc: New.
	* include/Makefile.am: Add dynamic_bitset.tcc.
	* include/Makefile.in: Add dynamic_bitset.tcc.
	* testsuite/tr2/dynamic_bitset/pr58729.cc: New.

Comments

Paolo Carlini Oct. 17, 2013, 9:05 a.m. UTC | #1
Hi,

On 10/17/2013 09:04 AM, Ed Smith-Rowland wrote:
> This patch bootstraps and tests clean on x86-64-linux.
>
> Truthfully, dynamic_bitset needs some more love wrt C++11 and a 
> testsuite.
> It got put in before it was baked really.
> That will be later.
Patch is Ok with me. Before committing you may want to test -m32 too.

Thanks,
Paolo.
Andreas Schwab Oct. 19, 2013, 10:04 a.m. UTC | #2
Paolo Carlini <paolo.carlini@oracle.com> writes:

> Before committing you may want to test -m32 too.

Where it in fact fails, see PR58804.

Andreas.
diff mbox

Patch

Index: include/tr2/dynamic_bitset
===================================================================
--- include/tr2/dynamic_bitset	(revision 203739)
+++ include/tr2/dynamic_bitset	(working copy)
@@ -137,7 +137,12 @@ 
 	if (__nbits % _S_bits_per_block > 0)
 	  ++__sz;
 	if (__sz != this->_M_w.size())
-	  this->_M_w.resize(__sz);
+	  {
+	    block_type __val = 0;
+	    if (__value)
+	      __val = std::numeric_limits<block_type>::max();
+	    this->_M_w.resize(__sz, __val);
+	  }
       }
 
       allocator_type
@@ -246,7 +251,7 @@ 
       bool
       _M_is_equal(const __dynamic_bitset_base& __x) const
       {
-	if (__x.size() == this->size())
+	if (__x._M_w.size() == this->_M_w.size())
 	  {
 	    for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
 	      if (this->_M_w[__i] != __x._M_w[__i])
@@ -260,7 +265,7 @@ 
       bool
       _M_is_less(const __dynamic_bitset_base& __x) const
       {
-	if (__x.size() == this->size())
+	if (__x._M_w.size() == this->_M_w.size())
 	  {
 	    for (size_t __i = this->_M_w.size(); __i > 0; --__i)
 	      {
@@ -297,9 +302,9 @@ 
       bool
       _M_is_subset_of(const __dynamic_bitset_base& __b)
       {
-	if (__b.size() == this->size())
+	if (__b._M_w.size() == this->_M_w.size())
 	  {
-	    for (size_t __i = 0; __i < _M_w.size(); ++__i)
+	    for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
 	      if (this->_M_w[__i] != (this->_M_w[__i] | __b._M_w[__i]))
 		return false;
 	    return true;
@@ -364,140 +369,6 @@ 
       }
     };
 
-  // Definitions of non-inline functions from __dynamic_bitset_base.
-  template<typename _WordT, typename _Alloc>
-    void
-    __dynamic_bitset_base<_WordT, _Alloc>::_M_do_left_shift(size_t __shift)
-    {
-      if (__builtin_expect(__shift != 0, 1))
-	{
-	  const size_t __wshift = __shift / _S_bits_per_block;
-	  const size_t __offset = __shift % _S_bits_per_block;
-
-	  if (__offset == 0)
-	    for (size_t __n = this->_M_w.size() - 1; __n >= __wshift; --__n)
-	      this->_M_w[__n] = this->_M_w[__n - __wshift];
-	  else
-	    {
-	      const size_t __sub_offset = _S_bits_per_block - __offset;
-	      for (size_t __n = _M_w.size() - 1; __n > __wshift; --__n)
-		this->_M_w[__n] = ((this->_M_w[__n - __wshift] << __offset)
-			     | (this->_M_w[__n - __wshift - 1] >> __sub_offset));
-	      this->_M_w[__wshift] = this->_M_w[0] << __offset;
-	    }
-
-	  //// std::fill(this->_M_w.begin(), this->_M_w.begin() + __wshift,
-	  ////          static_cast<_WordT>(0));
-	}
-    }
-
-  template<typename _WordT, typename _Alloc>
-    void
-    __dynamic_bitset_base<_WordT, _Alloc>::_M_do_right_shift(size_t __shift)
-    {
-      if (__builtin_expect(__shift != 0, 1))
-	{
-	  const size_t __wshift = __shift / _S_bits_per_block;
-	  const size_t __offset = __shift % _S_bits_per_block;
-	  const size_t __limit = this->_M_w.size() - __wshift - 1;
-
-	  if (__offset == 0)
-	    for (size_t __n = 0; __n <= __limit; ++__n)
-	      this->_M_w[__n] = this->_M_w[__n + __wshift];
-	  else
-	    {
-	      const size_t __sub_offset = (_S_bits_per_block
-					   - __offset);
-	      for (size_t __n = 0; __n < __limit; ++__n)
-		this->_M_w[__n] = ((this->_M_w[__n + __wshift] >> __offset)
-			     | (this->_M_w[__n + __wshift + 1] << __sub_offset));
-	      this->_M_w[__limit] = this->_M_w[_M_w.size()-1] >> __offset;
-	    }
-
-	  ////std::fill(this->_M_w.begin() + __limit + 1, this->_M_w.end(),
-	  ////          static_cast<_WordT>(0));
-	}
-    }
-
-  template<typename _WordT, typename _Alloc>
-    unsigned long
-    __dynamic_bitset_base<_WordT, _Alloc>::_M_do_to_ulong() const
-    {
-      size_t __n = sizeof(unsigned long) / sizeof(block_type);
-      for (size_t __i = __n; __i < this->_M_w.size(); ++__i)
-	if (this->_M_w[__i])
-	  __throw_overflow_error(__N("__dynamic_bitset_base::_M_do_to_ulong"));
-      unsigned long __res = 0UL;
-      for (size_t __i = 0; __i < __n && __i < this->_M_w.size(); ++__i)
-	__res += this->_M_w[__i] << (__i * _S_bits_per_block);
-      return __res;
-    }
-
-  template<typename _WordT, typename _Alloc>
-    unsigned long long
-    __dynamic_bitset_base<_WordT, _Alloc>::_M_do_to_ullong() const
-    {
-      size_t __n = sizeof(unsigned long long) / sizeof(block_type);
-      for (size_t __i = __n; __i < this->_M_w.size(); ++__i)
-	if (this->_M_w[__i])
-	  __throw_overflow_error(__N("__dynamic_bitset_base::_M_do_to_ullong"));
-      unsigned long long __res = 0ULL;
-      for (size_t __i = 0; __i < __n && __i < this->_M_w.size(); ++__i)
-	__res += this->_M_w[__i] << (__i * _S_bits_per_block);
-      return __res;
-    }
-
-  template<typename _WordT, typename _Alloc>
-    size_t
-    __dynamic_bitset_base<_WordT, _Alloc>
-    ::_M_do_find_first(size_t __not_found) const
-    {
-      for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
-	{
-	  _WordT __thisword = this->_M_w[__i];
-	  if (__thisword != static_cast<_WordT>(0))
-	    return (__i * _S_bits_per_block
-		    + __builtin_ctzl(__thisword));
-	}
-      // not found, so return an indication of failure.
-      return __not_found;
-    }
-
-  template<typename _WordT, typename _Alloc>
-    size_t
-    __dynamic_bitset_base<_WordT, _Alloc>
-    ::_M_do_find_next(size_t __prev, size_t __not_found) const
-    {
-      // make bound inclusive
-      ++__prev;
-
-      // check out of bounds
-      if (__prev >= this->_M_w.size() * _S_bits_per_block)
-	return __not_found;
-
-      // search first word
-      size_t __i = _S_whichword(__prev);
-      _WordT __thisword = this->_M_w[__i];
-
-      // mask off bits below bound
-      __thisword &= (~static_cast<_WordT>(0)) << _S_whichbit(__prev);
-
-      if (__thisword != static_cast<_WordT>(0))
-	return (__i * _S_bits_per_block
-		+ __builtin_ctzl(__thisword));
-
-      // check subsequent words
-      for (++__i; __i < this->_M_w.size(); ++__i)
-	{
-	  __thisword = this->_M_w[__i];
-	  if (__thisword != static_cast<_WordT>(0))
-	    return (__i * _S_bits_per_block
-		    + __builtin_ctzl(__thisword));
-	}
-      // not found, so return an indication of failure.
-      return __not_found;
-    } // end _M_do_find_next
-
   /**
    *  @brief  The %dynamic_bitset class represents a sequence of bits.
    *
@@ -594,6 +465,15 @@ 
 	  this->_M_hiword() &= ~((~static_cast<block_type>(0)) << __shift);
       }
 
+      //  Set the unused bits in the uppermost word.
+      void
+      _M_do_fill()
+      {
+	size_type __shift = this->_M_Nb % bits_per_block;
+	if (__shift > 0)
+	  this->_M_hiword() |= ((~static_cast<block_type>(0)) << __shift);
+      }
+
       /**
        *  These versions of single-bit set, reset, flip, and test
        *  do no range checking.
@@ -847,6 +727,8 @@ 
       void
       resize(size_type __nbits, bool __value = false)
       {
+	if (__value)
+	  this->_M_do_fill();
 	this->_M_resize(__nbits, __value);
 	this->_M_Nb = __nbits;
 	this->_M_do_sanitize();
@@ -1240,33 +1122,21 @@ 
       bool
       is_proper_subset_of(const dynamic_bitset& __b) const
       { return this->_M_is_proper_subset_of(__b); }
+
+      friend bool
+      operator==(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+		 const dynamic_bitset<_WordT, _Alloc>& __rhs)
+      { return __lhs._M_is_equal(__rhs); }
+
+      friend bool
+      operator<(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+		const dynamic_bitset<_WordT, _Alloc>& __rhs)
+      { return __lhs._M_is_less(__rhs); }
     };
 
-  // Definitions of non-inline member functions.
   template<typename _WordT, typename _Alloc>
-    template<typename _CharT, typename _Traits>
-      void
-      dynamic_bitset<_WordT, _Alloc>::
-      _M_copy_from_ptr(const _CharT* __str, size_t __len,
-		       size_t __pos, size_t __n, _CharT __zero, _CharT __one)
-      {
-	reset();
-	const size_t __nbits = std::min(_M_Nb, std::min(__n, __len - __pos));
-	for (size_t __i = __nbits; __i > 0; --__i)
-	  {
-	    const _CharT __c = __str[__pos + __nbits - __i];
-	    if (_Traits::eq(__c, __zero))
-	      ;
-	    else if (_Traits::eq(__c, __one))
-	      _M_unchecked_set(__i - 1);
-	    else
-	      __throw_invalid_argument(__N("dynamic_bitset::_M_copy_from_ptr"));
-	  }
-      }
-
-  template<typename _WordT, typename _Alloc>
     template<typename _CharT, typename _Traits, typename _Alloc1>
-      void
+      inline void
       dynamic_bitset<_WordT, _Alloc>::
       _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc1>& __str,
 			_CharT __zero, _CharT __one) const
@@ -1280,38 +1150,27 @@ 
 
   //@{
   /// These comparisons for equality/inequality are, well, @e bitwise.
-  template<typename _WordT, typename _Alloc>
-    bool
-    operator==(const dynamic_bitset<_WordT, _Alloc>& __lhs,
-	       const dynamic_bitset<_WordT, _Alloc>& __rhs)
-    { return __lhs._M_is_equal(__rhs); }
 
   template<typename _WordT, typename _Alloc>
-    bool
+    inline bool
     operator!=(const dynamic_bitset<_WordT, _Alloc>& __lhs,
 	       const dynamic_bitset<_WordT, _Alloc>& __rhs)
-    { return !__lhs._M_is_equal(__rhs); }
+    { return !(__lhs == __rhs); }
 
   template<typename _WordT, typename _Alloc>
-    bool
-    operator<(const dynamic_bitset<_WordT, _Alloc>& __lhs,
-	      const dynamic_bitset<_WordT, _Alloc>& __rhs)
-    { return __lhs._M_is_less(__rhs); }
-
-  template<typename _WordT, typename _Alloc>
-    bool
+    inline bool
     operator<=(const dynamic_bitset<_WordT, _Alloc>& __lhs,
 	       const dynamic_bitset<_WordT, _Alloc>& __rhs)
     { return !(__lhs > __rhs); }
 
   template<typename _WordT, typename _Alloc>
-    bool
+    inline bool
     operator>(const dynamic_bitset<_WordT, _Alloc>& __lhs,
 	      const dynamic_bitset<_WordT, _Alloc>& __rhs)
     { return __rhs < __lhs; }
 
   template<typename _WordT, typename _Alloc>
-    bool
+    inline bool
     operator>=(const dynamic_bitset<_WordT, _Alloc>& __lhs,
 	       const dynamic_bitset<_WordT, _Alloc>& __rhs)
     { return !(__lhs < __rhs); }
@@ -1368,8 +1227,9 @@ 
     }
   //@}
 
-  //@{
   /**
+   *  @defgroup Global I/O operators for bitsets.
+   *  @{
    *  @brief Global I/O operators for bitsets.
    *
    *  Direct I/O between streams and bitsets is supported.  Output is
@@ -1377,81 +1237,9 @@ 
    *  and '1' characters.  The %dynamic_bitset will grow as necessary
    *  to hold the string of bits.
    */
-  template<typename _CharT, typename _Traits,
-	   typename _WordT, typename _Alloc>
-    std::basic_istream<_CharT, _Traits>&
-    operator>>(std::basic_istream<_CharT, _Traits>& __is,
-	       dynamic_bitset<_WordT, _Alloc>& __x)
-    {
-      typedef typename _Traits::char_type          char_type;
-      typedef std::basic_istream<_CharT, _Traits>  __istream_type;
-      typedef typename __istream_type::ios_base    __ios_base;
-
-      std::basic_string<_CharT, _Traits> __tmp;
-      __tmp.reserve(__x.size());
-
-      const char_type __zero = __is.widen('0');
-      const char_type __one = __is.widen('1');
-
-      typename __ios_base::iostate __state = __ios_base::goodbit;
-      typename __istream_type::sentry __sentry(__is);
-      if (__sentry)
-	{
-	  __try
-	    {
-	      while (1)
-		{
-		  static typename _Traits::int_type __eof = _Traits::eof();
-
-		  typename _Traits::int_type __c1 = __is.rdbuf()->sbumpc();
-		  if (_Traits::eq_int_type(__c1, __eof))
-		    {
-		      __state |= __ios_base::eofbit;
-		      break;
-		    }
-		  else
-		    {
-		      const char_type __c2 = _Traits::to_char_type(__c1);
-		      if (_Traits::eq(__c2, __zero))
-			__tmp.push_back(__zero);
-		      else if (_Traits::eq(__c2, __one))
-			__tmp.push_back(__one);
-		      else if (_Traits::
-			       eq_int_type(__is.rdbuf()->sputbackc(__c2),
-					   __eof))
-			{
-			  __state |= __ios_base::failbit;
-			  break;
-			}
-		      else
-			break;
-		    }
-		}
-	    }
-	  __catch(__cxxabiv1::__forced_unwind&)
-	    {
-	      __is._M_setstate(__ios_base::badbit);
-	      __throw_exception_again;
-	    }
-	  __catch(...)
-	    { __is._M_setstate(__ios_base::badbit); }
-	}
-
-      __x.resize(__tmp.size());
-
-      if (__tmp.empty() && __x.size())
-	__state |= __ios_base::failbit;
-      else
-	__x._M_copy_from_string(__tmp, static_cast<size_t>(0), __x.size(),
-				__zero, __one);
-      if (__state)
-	__is.setstate(__state);
-      return __is;
-    }
-
   template <typename _CharT, typename _Traits,
 	    typename _WordT, typename _Alloc>
-    std::basic_ostream<_CharT, _Traits>&
+    inline std::basic_ostream<_CharT, _Traits>&
     operator<<(std::basic_ostream<_CharT, _Traits>& __os,
 	       const dynamic_bitset<_WordT, _Alloc>& __x)
     {
@@ -1461,12 +1249,14 @@ 
       __x._M_copy_to_string(__tmp, __ct.widen('0'), __ct.widen('1'));
       return __os << __tmp;
     }
-  //@}
+  /**
+   *  @}
+   */
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // tr2
 } // std
 
-#undef _GLIBCXX_BITSET_BITS_PER_WORD
+#include <tr2/dynamic_bitset.tcc>
 
 #endif /* _GLIBCXX_TR2_DYNAMIC_BITSET */
Index: include/tr2/dynamic_bitset.tcc
===================================================================
--- include/tr2/dynamic_bitset.tcc	(revision 0)
+++ include/tr2/dynamic_bitset.tcc	(working copy)
@@ -0,0 +1,286 @@ 
+// TR2 <dynamic_bitset> -*- C++ -*-
+
+// Copyright (C) 2009-2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/dynamic_bitset.tcc
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{tr2/dynamic_bitset}
+ */
+
+#ifndef _GLIBCXX_TR2_DYNAMIC_BITSET_TCC
+#define _GLIBCXX_TR2_DYNAMIC_BITSET_TCC 1
+
+#pragma GCC system_header
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  // Definitions of non-inline functions from __dynamic_bitset_base.
+  template<typename _WordT, typename _Alloc>
+    void
+    __dynamic_bitset_base<_WordT, _Alloc>::_M_do_left_shift(size_t __shift)
+    {
+      if (__builtin_expect(__shift != 0, 1))
+	{
+	  const size_t __wshift = __shift / _S_bits_per_block;
+	  const size_t __offset = __shift % _S_bits_per_block;
+
+	  if (__offset == 0)
+	    for (size_t __n = this->_M_w.size() - 1; __n >= __wshift; --__n)
+	      this->_M_w[__n] = this->_M_w[__n - __wshift];
+	  else
+	    {
+	      const size_t __sub_offset = _S_bits_per_block - __offset;
+	      for (size_t __n = _M_w.size() - 1; __n > __wshift; --__n)
+		this->_M_w[__n] = ((this->_M_w[__n - __wshift] << __offset)
+			     | (this->_M_w[__n - __wshift - 1] >> __sub_offset));
+	      this->_M_w[__wshift] = this->_M_w[0] << __offset;
+	    }
+
+	  //// std::fill(this->_M_w.begin(), this->_M_w.begin() + __wshift,
+	  ////          static_cast<_WordT>(0));
+	}
+    }
+
+  template<typename _WordT, typename _Alloc>
+    void
+    __dynamic_bitset_base<_WordT, _Alloc>::_M_do_right_shift(size_t __shift)
+    {
+      if (__builtin_expect(__shift != 0, 1))
+	{
+	  const size_t __wshift = __shift / _S_bits_per_block;
+	  const size_t __offset = __shift % _S_bits_per_block;
+	  const size_t __limit = this->_M_w.size() - __wshift - 1;
+
+	  if (__offset == 0)
+	    for (size_t __n = 0; __n <= __limit; ++__n)
+	      this->_M_w[__n] = this->_M_w[__n + __wshift];
+	  else
+	    {
+	      const size_t __sub_offset = (_S_bits_per_block
+					   - __offset);
+	      for (size_t __n = 0; __n < __limit; ++__n)
+		this->_M_w[__n] = ((this->_M_w[__n + __wshift] >> __offset)
+			     | (this->_M_w[__n + __wshift + 1] << __sub_offset));
+	      this->_M_w[__limit] = this->_M_w[_M_w.size()-1] >> __offset;
+	    }
+
+	  ////std::fill(this->_M_w.begin() + __limit + 1, this->_M_w.end(),
+	  ////          static_cast<_WordT>(0));
+	}
+    }
+
+  template<typename _WordT, typename _Alloc>
+    unsigned long
+    __dynamic_bitset_base<_WordT, _Alloc>::_M_do_to_ulong() const
+    {
+      size_t __n = sizeof(unsigned long) / sizeof(block_type);
+      for (size_t __i = __n; __i < this->_M_w.size(); ++__i)
+	if (this->_M_w[__i])
+	  __throw_overflow_error(__N("__dynamic_bitset_base::_M_do_to_ulong"));
+      unsigned long __res = 0UL;
+      for (size_t __i = 0; __i < __n && __i < this->_M_w.size(); ++__i)
+	__res += this->_M_w[__i] << (__i * _S_bits_per_block);
+      return __res;
+    }
+
+  template<typename _WordT, typename _Alloc>
+    unsigned long long
+    __dynamic_bitset_base<_WordT, _Alloc>::_M_do_to_ullong() const
+    {
+      size_t __n = sizeof(unsigned long long) / sizeof(block_type);
+      for (size_t __i = __n; __i < this->_M_w.size(); ++__i)
+	if (this->_M_w[__i])
+	  __throw_overflow_error(__N("__dynamic_bitset_base::_M_do_to_ullong"));
+      unsigned long long __res = 0ULL;
+      for (size_t __i = 0; __i < __n && __i < this->_M_w.size(); ++__i)
+	__res += this->_M_w[__i] << (__i * _S_bits_per_block);
+      return __res;
+    }
+
+  template<typename _WordT, typename _Alloc>
+    size_t
+    __dynamic_bitset_base<_WordT, _Alloc>
+    ::_M_do_find_first(size_t __not_found) const
+    {
+      for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+	{
+	  _WordT __thisword = this->_M_w[__i];
+	  if (__thisword != static_cast<_WordT>(0))
+	    return (__i * _S_bits_per_block
+		    + __builtin_ctzl(__thisword));
+	}
+      // not found, so return an indication of failure.
+      return __not_found;
+    }
+
+  template<typename _WordT, typename _Alloc>
+    size_t
+    __dynamic_bitset_base<_WordT, _Alloc>
+    ::_M_do_find_next(size_t __prev, size_t __not_found) const
+    {
+      // make bound inclusive
+      ++__prev;
+
+      // check out of bounds
+      if (__prev >= this->_M_w.size() * _S_bits_per_block)
+	return __not_found;
+
+      // search first word
+      size_t __i = _S_whichword(__prev);
+      _WordT __thisword = this->_M_w[__i];
+
+      // mask off bits below bound
+      __thisword &= (~static_cast<_WordT>(0)) << _S_whichbit(__prev);
+
+      if (__thisword != static_cast<_WordT>(0))
+	return (__i * _S_bits_per_block
+		+ __builtin_ctzl(__thisword));
+
+      // check subsequent words
+      for (++__i; __i < this->_M_w.size(); ++__i)
+	{
+	  __thisword = this->_M_w[__i];
+	  if (__thisword != static_cast<_WordT>(0))
+	    return (__i * _S_bits_per_block
+		    + __builtin_ctzl(__thisword));
+	}
+      // not found, so return an indication of failure.
+      return __not_found;
+    } // end _M_do_find_next
+
+  // Definitions of non-inline member functions.
+  template<typename _WordT, typename _Alloc>
+    template<typename _CharT, typename _Traits>
+      void
+      dynamic_bitset<_WordT, _Alloc>::
+      _M_copy_from_ptr(const _CharT* __str, size_t __len,
+		       size_t __pos, size_t __n, _CharT __zero, _CharT __one)
+      {
+	reset();
+	const size_t __nbits = std::min(_M_Nb, std::min(__n, __len - __pos));
+	for (size_t __i = __nbits; __i > 0; --__i)
+	  {
+	    const _CharT __c = __str[__pos + __nbits - __i];
+	    if (_Traits::eq(__c, __zero))
+	      ;
+	    else if (_Traits::eq(__c, __one))
+	      _M_unchecked_set(__i - 1);
+	    else
+	      __throw_invalid_argument(__N("dynamic_bitset::_M_copy_from_ptr"));
+	  }
+      }
+
+  /**
+   *  @defgroup Global I/O operators for bitsets.
+   *  @{
+   *  @brief Global I/O operators for bitsets.
+   *
+   *  Direct I/O between streams and bitsets is supported.  Output is
+   *  straightforward.  Input will skip whitespace and only accept '0'
+   *  and '1' characters.  The %dynamic_bitset will grow as necessary
+   *  to hold the string of bits.
+   */
+  template<typename _CharT, typename _Traits,
+	   typename _WordT, typename _Alloc>
+    std::basic_istream<_CharT, _Traits>&
+    operator>>(std::basic_istream<_CharT, _Traits>& __is,
+	       dynamic_bitset<_WordT, _Alloc>& __x)
+    {
+      typedef typename _Traits::char_type          char_type;
+      typedef std::basic_istream<_CharT, _Traits>  __istream_type;
+      typedef typename __istream_type::ios_base    __ios_base;
+
+      std::basic_string<_CharT, _Traits> __tmp;
+      __tmp.reserve(__x.size());
+
+      const char_type __zero = __is.widen('0');
+      const char_type __one = __is.widen('1');
+
+      typename __ios_base::iostate __state = __ios_base::goodbit;
+      typename __istream_type::sentry __sentry(__is);
+      if (__sentry)
+	{
+	  __try
+	    {
+	      while (1)
+		{
+		  static typename _Traits::int_type __eof = _Traits::eof();
+
+		  typename _Traits::int_type __c1 = __is.rdbuf()->sbumpc();
+		  if (_Traits::eq_int_type(__c1, __eof))
+		    {
+		      __state |= __ios_base::eofbit;
+		      break;
+		    }
+		  else
+		    {
+		      const char_type __c2 = _Traits::to_char_type(__c1);
+		      if (_Traits::eq(__c2, __zero))
+			__tmp.push_back(__zero);
+		      else if (_Traits::eq(__c2, __one))
+			__tmp.push_back(__one);
+		      else if (_Traits::
+			       eq_int_type(__is.rdbuf()->sputbackc(__c2),
+					   __eof))
+			{
+			  __state |= __ios_base::failbit;
+			  break;
+			}
+		      else
+			break;
+		    }
+		}
+	    }
+	  __catch(__cxxabiv1::__forced_unwind&)
+	    {
+	      __is._M_setstate(__ios_base::badbit);
+	      __throw_exception_again;
+	    }
+	  __catch(...)
+	    { __is._M_setstate(__ios_base::badbit); }
+	}
+
+      __x.resize(__tmp.size());
+
+      if (__tmp.empty() && __x.size())
+	__state |= __ios_base::failbit;
+      else
+	__x._M_copy_from_string(__tmp, static_cast<size_t>(0), __x.size(),
+				__zero, __one);
+      if (__state)
+	__is.setstate(__state);
+      return __is;
+    }
+  /**
+   *  @}
+   */
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // tr2
+} // std
+
+#endif /* _GLIBCXX_TR2_DYNAMIC_BITSET_TCC */
Index: include/Makefile.am
===================================================================
--- include/Makefile.am	(revision 203739)
+++ include/Makefile.am	(working copy)
@@ -623,6 +623,7 @@ 
 	${tr2_srcdir}/bool_set \
 	${tr2_srcdir}/bool_set.tcc \
 	${tr2_srcdir}/dynamic_bitset \
+	${tr2_srcdir}/dynamic_bitset.tcc \
 	${tr2_srcdir}/ratio \
 	${tr2_srcdir}/type_traits
 
Index: include/Makefile.in
===================================================================
--- include/Makefile.in	(revision 203739)
+++ include/Makefile.in	(working copy)
@@ -888,6 +888,7 @@ 
 	${tr2_srcdir}/bool_set \
 	${tr2_srcdir}/bool_set.tcc \
 	${tr2_srcdir}/dynamic_bitset \
+	${tr2_srcdir}/dynamic_bitset.tcc \
 	${tr2_srcdir}/ratio \
 	${tr2_srcdir}/type_traits
 
Index: testsuite/tr2/dynamic_bitset/pr58729.cc
===================================================================
--- testsuite/tr2/dynamic_bitset/pr58729.cc	(revision 0)
+++ testsuite/tr2/dynamic_bitset/pr58729.cc	(working copy)
@@ -0,0 +1,64 @@ 
+// { dg-options "-std=gnu++11" }
+
+// 2013-10-15  Edward M. Smith-Rowland  <3dw4rd@verizon.net>
+//
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// libstdc++/58729
+
+#include <tr2/dynamic_bitset>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::tr2::dynamic_bitset<> pdb2{};
+
+  pdb2.resize(10, true);
+  VERIFY (pdb2 == std::tr2::dynamic_bitset<>{"1111111111"});
+
+  pdb2.resize(15);
+  VERIFY (pdb2 == std::tr2::dynamic_bitset<>{"000001111111111"});
+
+  pdb2.flip();
+  VERIFY (pdb2 == std::tr2::dynamic_bitset<>{"111110000000000"});
+
+  VERIFY (pdb2.size() == 15);
+  VERIFY (pdb2.count() == 5);
+
+  pdb2.resize(20, false);
+  VERIFY (pdb2 == std::tr2::dynamic_bitset<>{"00000111110000000000"});
+
+  pdb2.resize(25, true);
+  VERIFY (pdb2 == std::tr2::dynamic_bitset<>{"1111100000111110000000000"});
+
+  pdb2.resize(75, true);
+  VERIFY (pdb2 == std::tr2::dynamic_bitset<>{"1111111111111111111111111"
+					     "1111111111111111111111111"
+					     "1111100000111110000000000"});
+
+  VERIFY (pdb2.size() == 75);
+  VERIFY (pdb2.count() == 60);
+}
+
+int
+main()
+{
+  test01();
+  return 0;
+}