[gcc/devel/omp/gcc-9] PR libstdc++/92059 fix several bugs in tr2::dynamic_bitset

Tobias Burnus burnus@gcc.gnu.org
Thu Mar 5 14:13:00 GMT 2020


https://gcc.gnu.org/g:de5a2a192393292ec30ee686fae2ac14fa982159

commit de5a2a192393292ec30ee686fae2ac14fa982159
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Oct 24 13:53:55 2019 +0100

    PR libstdc++/92059 fix several bugs in tr2::dynamic_bitset
    
    Backport from mainline
    2019-10-11  Jonathan Wakely  <jwakely@redhat.com>
    
    	PR libstdc++/92059
    	* include/tr2/dynamic_bitset (__dynamic_bitset_base): Define all
    	special member functions as defaulted. Add noexcept to most members.
    	(__dynamic_bitset_base(size_t, unsigned long long, const _Alloc&)):
    	Mask off unwanted bits in the __val parameter. Avoid undefined left
    	shifts.
    	(__dynamic_bitset_base::_M_assign): Remove.
    	(__dynamic_bitset_base::_M_do_reset): Use std::fill.
    	(__dynamic_bitset_base::_M_are_all_aux): Avoid integer promotion when
    	block_type has lower rank than int.
    	(dynamic_bitset): Add noexcept to most members. Use injected-class-name
    	in return types and parameter types.
    	(dynamic_bitset::_M_Nb): Add default member initializer.
    	(dynamic_bitset(), dynamic_bitset(const dynamic_bitset&)): Define as
    	defaulted.
    	(dynamic_bitset(dynamic_bitset&&)): Clear source object after move.
    	(dynamic_bitset::operator=(const dynamic_bitset&)): Define as
    	defaulted.
    	(dynamic_bitset::operator=(dynamic_bitset&&)): Add noexcept-specifier.
    	Define without using swap, to propagate allocator correctly.
    	(dynamic_bitset(const char*, const _Alloc&)): Use strlen.
    	(dynamic_bitset::_M_do_sanitize, dynamic_bitset::_M_do_fill): Use
    	casts to avoid unwanted integer promotions.
    	(dynamic_bitset::_M_copy_from_ptr): Rearrange template parameters and
    	add default template arguments and default argument to simplify usage.
    	(dynamic_bitset::_M_copy_from_string): Adjust call to _M_copy_from_ptr.
    	(operator==(const dynamic_bitset&, const dynamic_bitset&))
    	(operator<(const dynamic_bitset&, const dynamic_bitset&)): Use _M_Nb.
    	* include/tr2/dynamic_bitset.tcc (dynamic_bitset::_M_copy_from_ptr):
    	Adjust template parameters to match declaration.
    	* testsuite/tr2/dynamic_bitset/cmp.cc: New test.
    	* testsuite/tr2/dynamic_bitset/cons.cc: New test.
    	* testsuite/tr2/dynamic_bitset/copy.cc: New test.
    	* testsuite/tr2/dynamic_bitset/move.cc: New test.
    	* testsuite/tr2/dynamic_bitset/pr92059.cc: New test.
    
    From-SVN: r277376

Diff:
---
 libstdc++-v3/ChangeLog                             |  41 +++
 libstdc++-v3/include/tr2/dynamic_bitset            | 295 ++++++++++-----------
 libstdc++-v3/include/tr2/dynamic_bitset.tcc        |   2 +-
 libstdc++-v3/testsuite/tr2/dynamic_bitset/cmp.cc   |  50 ++++
 libstdc++-v3/testsuite/tr2/dynamic_bitset/cons.cc  | 105 ++++++++
 libstdc++-v3/testsuite/tr2/dynamic_bitset/copy.cc  |  55 ++++
 libstdc++-v3/testsuite/tr2/dynamic_bitset/move.cc  |  53 ++++
 .../testsuite/tr2/dynamic_bitset/pr92059.cc        |  36 +++
 8 files changed, 483 insertions(+), 154 deletions(-)

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 33e56ea..2b7a0e1 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,44 @@
+2019-10-24  Jonathan Wakely  <jwakely@redhat.com>
+
+	Backport from mainline
+	2019-10-11  Jonathan Wakely  <jwakely@redhat.com>
+
+	PR libstdc++/92059
+	* include/tr2/dynamic_bitset (__dynamic_bitset_base): Define all
+	special member functions as defaulted. Add noexcept to most members.
+	(__dynamic_bitset_base(size_t, unsigned long long, const _Alloc&)):
+	Mask off unwanted bits in the __val parameter. Avoid undefined left
+	shifts.
+	(__dynamic_bitset_base::_M_assign): Remove.
+	(__dynamic_bitset_base::_M_do_reset): Use std::fill.
+	(__dynamic_bitset_base::_M_are_all_aux): Avoid integer promotion when
+	block_type has lower rank than int.
+	(dynamic_bitset): Add noexcept to most members. Use injected-class-name
+	in return types and parameter types.
+	(dynamic_bitset::_M_Nb): Add default member initializer.
+	(dynamic_bitset(), dynamic_bitset(const dynamic_bitset&)): Define as
+	defaulted.
+	(dynamic_bitset(dynamic_bitset&&)): Clear source object after move.
+	(dynamic_bitset::operator=(const dynamic_bitset&)): Define as
+	defaulted.
+	(dynamic_bitset::operator=(dynamic_bitset&&)): Add noexcept-specifier.
+	Define without using swap, to propagate allocator correctly.
+	(dynamic_bitset(const char*, const _Alloc&)): Use strlen.
+	(dynamic_bitset::_M_do_sanitize, dynamic_bitset::_M_do_fill): Use
+	casts to avoid unwanted integer promotions.
+	(dynamic_bitset::_M_copy_from_ptr): Rearrange template parameters and
+	add default template arguments and default argument to simplify usage.
+	(dynamic_bitset::_M_copy_from_string): Adjust call to _M_copy_from_ptr.
+	(operator==(const dynamic_bitset&, const dynamic_bitset&))
+	(operator<(const dynamic_bitset&, const dynamic_bitset&)): Use _M_Nb.
+	* include/tr2/dynamic_bitset.tcc (dynamic_bitset::_M_copy_from_ptr):
+	Adjust template parameters to match declaration.
+	* testsuite/tr2/dynamic_bitset/cmp.cc: New test.
+	* testsuite/tr2/dynamic_bitset/cons.cc: New test.
+	* testsuite/tr2/dynamic_bitset/copy.cc: New test.
+	* testsuite/tr2/dynamic_bitset/move.cc: New test.
+	* testsuite/tr2/dynamic_bitset/pr92059.cc: New test.
+
 2019-09-12  Jonathan Wakely  <jwakely@redhat.com>
 
 	PR libstdc++/91748
diff --git a/libstdc++-v3/include/tr2/dynamic_bitset b/libstdc++-v3/include/tr2/dynamic_bitset
index 434a4cc..28c877c 100644
--- a/libstdc++-v3/include/tr2/dynamic_bitset
+++ b/libstdc++-v3/include/tr2/dynamic_bitset
@@ -34,10 +34,9 @@
 #include <limits>
 #include <vector>
 #include <string>
-#include <memory> // For std::allocator
-#include <bits/functexcept.h>   // For invalid_argument, out_of_range,
-				// overflow_error
-#include <iosfwd>
+#include <istream>
+#include <bits/functexcept.h>
+#include <bits/stl_algo.h>	// For fill
 #include <bits/cxxabi_forced.h>
 
 namespace std _GLIBCXX_VISIBILITY(default)
@@ -76,41 +75,48 @@ namespace tr2
       std::vector<block_type, allocator_type> _M_w;
 
       explicit
-      __dynamic_bitset_base(const allocator_type& __alloc = allocator_type())
+      __dynamic_bitset_base(const allocator_type& __alloc)
       : _M_w(__alloc)
       { }
 
-      explicit
-      __dynamic_bitset_base(__dynamic_bitset_base&& __b)
-      { this->_M_w.swap(__b._M_w); }
+      __dynamic_bitset_base() = default;
+      __dynamic_bitset_base(const __dynamic_bitset_base&) = default;
+      __dynamic_bitset_base(__dynamic_bitset_base&& __b) = default;
+      __dynamic_bitset_base& operator=(const __dynamic_bitset_base&) = default;
+      __dynamic_bitset_base& operator=(__dynamic_bitset_base&&) = default;
+      ~__dynamic_bitset_base() = default;
 
       explicit
       __dynamic_bitset_base(size_type __nbits, unsigned long long __val = 0ULL,
 			   const allocator_type& __alloc = allocator_type())
-      : _M_w(__nbits / _S_bits_per_block
-	     + (__nbits % _S_bits_per_block > 0),
-	     __val, __alloc)
+      : _M_w(__nbits / _S_bits_per_block + (__nbits % _S_bits_per_block > 0),
+	     block_type(0), __alloc)
       {
-	unsigned long long __mask = ~static_cast<block_type>(0);
-	size_t __n = std::min(this->_M_w.size(),
-			      sizeof(unsigned long long) / sizeof(block_type));
-	for (size_t __i = 0; __i < __n; ++__i)
+	if (__nbits < std::numeric_limits<decltype(__val)>::digits)
+	  __val &= ~(-1ULL << __nbits);
+	if (__val == 0)
+	  return;
+
+	if _GLIBCXX17_CONSTEXPR (sizeof(__val) == sizeof(block_type))
+	  _M_w[0] = __val;
+	else
 	  {
-	    this->_M_w[__i] = (__val & __mask) >> (__i * _S_bits_per_block);
-	    __mask <<= _S_bits_per_block;
+	    const size_t __n
+	      = std::min(_M_w.size(), sizeof(__val) / sizeof(block_type));
+	    for (size_t __i = 0; __val && __i < __n; ++__i)
+	      {
+		_M_w[__i] = static_cast<block_type>(__val);
+		__val >>= _S_bits_per_block;
+	      }
 	  }
       }
 
       void
-      _M_assign(const __dynamic_bitset_base& __b)
-      { this->_M_w = __b._M_w; }
-
-      void
-      _M_swap(__dynamic_bitset_base& __b)
+      _M_swap(__dynamic_bitset_base& __b) noexcept
       { this->_M_w.swap(__b._M_w); }
 
       void
-      _M_clear()
+      _M_clear() noexcept
       { this->_M_w.clear(); }
 
       void
@@ -129,7 +135,7 @@ namespace tr2
       }
 
       allocator_type
-      _M_get_allocator() const
+      _M_get_allocator() const noexcept
       { return this->_M_w.get_allocator(); }
 
       static size_type
@@ -149,23 +155,23 @@ namespace tr2
       { return (static_cast<block_type>(1)) << _S_whichbit(__pos); }
 
       block_type&
-      _M_getword(size_type __pos)
+      _M_getword(size_type __pos) noexcept
       { return this->_M_w[_S_whichword(__pos)]; }
 
       block_type
-      _M_getword(size_type __pos) const
+      _M_getword(size_type __pos) const noexcept
       { return this->_M_w[_S_whichword(__pos)]; }
 
       block_type&
-      _M_hiword()
+      _M_hiword() noexcept
       { return this->_M_w[_M_w.size() - 1]; }
 
       block_type
-      _M_hiword() const
+      _M_hiword() const noexcept
       { return this->_M_w[_M_w.size() - 1]; }
 
       void
-      _M_do_and(const __dynamic_bitset_base& __x)
+      _M_do_and(const __dynamic_bitset_base& __x) noexcept
       {
 	if (__x._M_w.size() == this->_M_w.size())
 	  for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
@@ -175,7 +181,7 @@ namespace tr2
       }
 
       void
-      _M_do_or(const __dynamic_bitset_base& __x)
+      _M_do_or(const __dynamic_bitset_base& __x) noexcept
       {
 	if (__x._M_w.size() == this->_M_w.size())
 	  for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
@@ -185,7 +191,7 @@ namespace tr2
       }
 
       void
-      _M_do_xor(const __dynamic_bitset_base& __x)
+      _M_do_xor(const __dynamic_bitset_base& __x) noexcept
       {
 	if (__x._M_w.size() == this->_M_w.size())
 	  for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
@@ -195,7 +201,7 @@ namespace tr2
       }
 
       void
-      _M_do_dif(const __dynamic_bitset_base& __x)
+      _M_do_dif(const __dynamic_bitset_base& __x) noexcept
       {
 	if (__x._M_w.size() == this->_M_w.size())
 	  for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
@@ -211,28 +217,27 @@ namespace tr2
       _M_do_right_shift(size_t __shift);
 
       void
-      _M_do_flip()
+      _M_do_flip() noexcept
       {
 	for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
 	  this->_M_w[__i] = ~this->_M_w[__i];
       }
 
       void
-      _M_do_set()
+      _M_do_set() noexcept
       {
 	for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
-	  this->_M_w[__i] = ~static_cast<block_type>(0);
+	  this->_M_w[__i] = static_cast<block_type>(-1);
       }
 
       void
-      _M_do_reset()
+      _M_do_reset() noexcept
       {
-	for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
-	  this->_M_w[__i] = static_cast<block_type>(0);
+	std::fill(_M_w.begin(), _M_w.end(), static_cast<block_type>(0));
       }
 
       bool
-      _M_is_equal(const __dynamic_bitset_base& __x) const
+      _M_is_equal(const __dynamic_bitset_base& __x) const noexcept
       {
 	if (__x._M_w.size() == this->_M_w.size())
 	  {
@@ -246,7 +251,7 @@ namespace tr2
       }
 
       bool
-      _M_is_less(const __dynamic_bitset_base& __x) const
+      _M_is_less(const __dynamic_bitset_base& __x) const noexcept
       {
 	if (__x._M_w.size() == this->_M_w.size())
 	  {
@@ -264,17 +269,17 @@ namespace tr2
       }
 
       size_t
-      _M_are_all_aux() const
+      _M_are_all_aux() const noexcept
       {
 	for (size_t __i = 0; __i < this->_M_w.size() - 1; ++__i)
-	  if (_M_w[__i] != ~static_cast<block_type>(0))
+	  if (_M_w[__i] != static_cast<block_type>(-1))
 	    return 0;
 	return ((this->_M_w.size() - 1) * _S_bits_per_block
 		+ __builtin_popcountll(this->_M_hiword()));
       }
 
       bool
-      _M_is_any() const
+      _M_is_any() const noexcept
       {
 	for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
 	  if (this->_M_w[__i] != static_cast<block_type>(0))
@@ -283,7 +288,7 @@ namespace tr2
       }
 
       bool
-      _M_is_subset_of(const __dynamic_bitset_base& __b)
+      _M_is_subset_of(const __dynamic_bitset_base& __b) noexcept
       {
 	if (__b._M_w.size() == this->_M_w.size())
 	  {
@@ -297,7 +302,7 @@ namespace tr2
       }
 
       bool
-      _M_is_proper_subset_of(const __dynamic_bitset_base& __b) const
+      _M_is_proper_subset_of(const __dynamic_bitset_base& __b) const noexcept
       {
 	if (this->is_subset_of(__b))
 	  {
@@ -311,7 +316,7 @@ namespace tr2
       }
 
       size_t
-      _M_do_count() const
+      _M_do_count() const noexcept
       {
 	size_t __result = 0;
 	for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
@@ -357,6 +362,7 @@ namespace tr2
    *
    *  See N2050,
    *  Proposal to Add a Dynamically Sizeable Bitset to the Standard Library.
+   *  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2050.pdf
    *
    *  In the general unoptimized case, storage is allocated in
    *  word-sized blocks.  Let B be the number of bits in a word, then
@@ -435,7 +441,7 @@ namespace tr2
       {
 	size_type __shift = this->_M_Nb % bits_per_block;
 	if (__shift > 0)
-	  this->_M_hiword() &= ~((~static_cast<block_type>(0)) << __shift);
+	  this->_M_hiword() &= block_type(~(block_type(-1) << __shift));
       }
 
       //  Set the unused bits in the uppermost word.
@@ -444,22 +450,22 @@ namespace tr2
       {
 	size_type __shift = this->_M_Nb % bits_per_block;
 	if (__shift > 0)
-	  this->_M_hiword() |= ((~static_cast<block_type>(0)) << __shift);
+	  this->_M_hiword() |= block_type(block_type(-1) << __shift);
       }
 
       /**
        *  These versions of single-bit set, reset, flip, and test
        *  do no range checking.
        */
-      dynamic_bitset<_WordT, _Alloc>&
-      _M_unchecked_set(size_type __pos)
+      dynamic_bitset&
+      _M_unchecked_set(size_type __pos) noexcept
       {
 	this->_M_getword(__pos) |= _Base::_S_maskbit(__pos);
 	return *this;
       }
 
-      dynamic_bitset<_WordT, _Alloc>&
-      _M_unchecked_set(size_type __pos, int __val)
+      dynamic_bitset&
+      _M_unchecked_set(size_type __pos, int __val) noexcept
       {
 	if (__val)
 	  this->_M_getword(__pos) |= _Base::_S_maskbit(__pos);
@@ -468,26 +474,26 @@ namespace tr2
 	return *this;
       }
 
-      dynamic_bitset<_WordT, _Alloc>&
-      _M_unchecked_reset(size_type __pos)
+      dynamic_bitset&
+      _M_unchecked_reset(size_type __pos) noexcept
       {
 	this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos);
 	return *this;
       }
 
-      dynamic_bitset<_WordT, _Alloc>&
-      _M_unchecked_flip(size_type __pos)
+      dynamic_bitset&
+      _M_unchecked_flip(size_type __pos) noexcept
       {
 	this->_M_getword(__pos) ^= _Base::_S_maskbit(__pos);
 	return *this;
       }
 
       bool
-      _M_unchecked_test(size_type __pos) const
+      _M_unchecked_test(size_type __pos) const noexcept
       { return ((this->_M_getword(__pos) & _Base::_S_maskbit(__pos))
 		!= static_cast<_WordT>(0)); }
 
-      size_type _M_Nb;
+      size_type _M_Nb = 0;
 
     public:
       /**
@@ -511,22 +517,16 @@ namespace tr2
 	block_type *_M_wp;
 	size_type _M_bpos;
 
-	// left undefined
-	reference();
-
       public:
-	reference(dynamic_bitset& __b, size_type __pos)
+	reference(dynamic_bitset& __b, size_type __pos) noexcept
 	{
 	  this->_M_wp = &__b._M_getword(__pos);
 	  this->_M_bpos = _Base::_S_whichbit(__pos);
 	}
 
-	~reference()
-	{ }
-
 	// For b[i] = __x;
 	reference&
-	operator=(bool __x)
+	operator=(bool __x) noexcept
 	{
 	  if (__x)
 	    *this->_M_wp |= _Base::_S_maskbit(this->_M_bpos);
@@ -537,7 +537,7 @@ namespace tr2
 
 	// For b[i] = b[__j];
 	reference&
-	operator=(const reference& __j)
+	operator=(const reference& __j) noexcept
 	{
 	  if ((*(__j._M_wp) & _Base::_S_maskbit(__j._M_bpos)))
 	    *this->_M_wp |= _Base::_S_maskbit(this->_M_bpos);
@@ -548,16 +548,16 @@ namespace tr2
 
 	// Flips the bit
 	bool
-	operator~() const
+	operator~() const noexcept
 	{ return (*(_M_wp) & _Base::_S_maskbit(this->_M_bpos)) == 0; }
 
 	// For __x = b[i];
-	operator bool() const
+	operator bool() const noexcept
 	{ return (*(this->_M_wp) & _Base::_S_maskbit(this->_M_bpos)) != 0; }
 
 	// For b[i].flip();
 	reference&
-	flip()
+	flip() noexcept
 	{
 	  *this->_M_wp ^= _Base::_S_maskbit(this->_M_bpos);
 	  return *this;
@@ -569,10 +569,14 @@ namespace tr2
       typedef bool const_reference;
 
       // 23.3.5.1 constructors:
+
+      /// All bits set to zero.
+      dynamic_bitset() = default;
+
       /// All bits set to zero.
       explicit
-      dynamic_bitset(const allocator_type& __alloc = allocator_type())
-      : _Base(__alloc), _M_Nb(0)
+      dynamic_bitset(const allocator_type& __alloc)
+      : _Base(__alloc)
       { }
 
       /// Initial bits bitwise-copied from a single word (others set to zero).
@@ -585,7 +589,7 @@ namespace tr2
 
       dynamic_bitset(initializer_list<block_type> __il,
 		     const allocator_type& __alloc = allocator_type())
-      : _Base(__alloc), _M_Nb(0)
+      : _Base(__alloc)
       { this->append(__il); }
 
       /**
@@ -609,8 +613,7 @@ namespace tr2
 		       __n = std::basic_string<_CharT, _Traits, _Alloc1>::npos,
 		       _CharT __zero = _CharT('0'), _CharT __one = _CharT('1'),
 		       const allocator_type& __alloc = allocator_type())
-	: _Base(__alloc),
-	  _M_Nb(0) // Watch for npos.
+	: _Base(__alloc)
 	{
 	  if (__pos > __str.size())
 	    __throw_out_of_range(__N("dynamic_bitset::bitset initial position "
@@ -619,8 +622,7 @@ namespace tr2
 	  // Watch for npos.
 	  this->_M_Nb = (__n > __str.size() ? __str.size() - __pos : __n);
 	  this->resize(this->_M_Nb);
-	  this->_M_copy_from_string(__str, __pos, __n,
-				    _CharT('0'), _CharT('1'));
+	  this->_M_copy_from_string(__str, __pos, __n);
 	}
 
       /**
@@ -633,61 +635,42 @@ namespace tr2
       explicit
       dynamic_bitset(const char* __str,
 		     const allocator_type& __alloc = allocator_type())
-      : _Base(__alloc)
+      : _Base(__builtin_strlen(__str), 0ULL, __alloc),
+	_M_Nb(__builtin_strlen(__str))
       {
-	size_t __len = 0;
-	if (__str)
-	  while (__str[__len] != '\0')
-	    ++__len;
-	this->resize(__len);
-	this->_M_copy_from_ptr<char,std::char_traits<char>>
-		   (__str, __len, 0, __len, '0', '1');
+	this->_M_copy_from_ptr(__str, _M_Nb, 0, _M_Nb);
       }
 
-      /**
-       *  @brief  Copy constructor.
-       */
-      dynamic_bitset(const dynamic_bitset& __b)
-      : _Base(__b), _M_Nb(__b.size())
-      { }
+      /// Copy constructor.
+      dynamic_bitset(const dynamic_bitset&) = default;
 
-      /**
-       *  @brief  Move constructor.
-       */
-      dynamic_bitset(dynamic_bitset&& __b)
-      : _Base(std::forward<_Base>(__b)), _M_Nb(__b.size())
-      { }
+      /// Move constructor.
+      dynamic_bitset(dynamic_bitset&& __b) noexcept
+      : _Base(std::move(__b)), _M_Nb(__b._M_Nb)
+      { __b.clear(); }
 
-      /**
-       *  @brief  Swap with another bitset.
-       */
+      /// Swap with another bitset.
       void
-      swap(dynamic_bitset& __b)
+      swap(dynamic_bitset& __b) noexcept
       {
 	this->_M_swap(__b);
 	std::swap(this->_M_Nb, __b._M_Nb);
       }
 
-      /**
-       *  @brief  Assignment.
-       */
-      dynamic_bitset&
-      operator=(const dynamic_bitset& __b)
-      {
-	if (&__b != this)
-	  {
-	    this->_M_assign(__b);
-	    this->_M_Nb = __b._M_Nb;
-	  }
-      }
+      /// Copy assignment operator.
+      dynamic_bitset& operator=(const dynamic_bitset&) = default;
 
-      /**
-       *  @brief  Move assignment.
-       */
+      /// Move assignment operator.
       dynamic_bitset&
       operator=(dynamic_bitset&& __b)
+      noexcept(std::is_nothrow_move_assignable<_Base>::value)
       {
-	this->swap(__b);
+	static_cast<_Base&>(*this) = static_cast<_Base&&>(__b);
+	_M_Nb = __b._M_Nb;
+	if _GLIBCXX17_CONSTEXPR (std::is_nothrow_move_assignable<_Base>::value)
+	  __b._M_Nb = 0;
+	else if (get_allocator() == __b.get_allocator())
+	  __b._M_Nb = 0;
 	return *this;
       }
 
@@ -695,7 +678,7 @@ namespace tr2
        *  @brief  Return the allocator for the bitset.
        */
       allocator_type
-      get_allocator() const
+      get_allocator() const noexcept
       { return this->_M_get_allocator(); }
 
       /**
@@ -734,6 +717,8 @@ namespace tr2
 	++this->_M_Nb;
       }
 
+      // XXX why is there no pop_back() member in the proposal?
+
       /**
        *  @brief  Append a block.
        */
@@ -770,36 +755,36 @@ namespace tr2
        *
        *  These should be self-explanatory.
        */
-      dynamic_bitset<_WordT, _Alloc>&
-      operator&=(const dynamic_bitset<_WordT, _Alloc>& __rhs)
+      dynamic_bitset&
+      operator&=(const dynamic_bitset& __rhs)
       {
 	this->_M_do_and(__rhs);
 	return *this;
       }
 
-      dynamic_bitset<_WordT, _Alloc>&
-      operator&=(dynamic_bitset<_WordT, _Alloc>&& __rhs)
+      dynamic_bitset&
+      operator&=(dynamic_bitset&& __rhs)
       {
 	this->_M_do_and(std::move(__rhs));
 	return *this;
       }
 
-      dynamic_bitset<_WordT, _Alloc>&
-      operator|=(const dynamic_bitset<_WordT, _Alloc>& __rhs)
+      dynamic_bitset&
+      operator|=(const dynamic_bitset& __rhs)
       {
 	this->_M_do_or(__rhs);
 	return *this;
       }
 
-      dynamic_bitset<_WordT, _Alloc>&
-      operator^=(const dynamic_bitset<_WordT, _Alloc>& __rhs)
+      dynamic_bitset&
+      operator^=(const dynamic_bitset& __rhs)
       {
 	this->_M_do_xor(__rhs);
 	return *this;
       }
 
-      dynamic_bitset<_WordT, _Alloc>&
-      operator-=(const dynamic_bitset<_WordT, _Alloc>& __rhs)
+      dynamic_bitset&
+      operator-=(const dynamic_bitset& __rhs)
       {
 	this->_M_do_dif(__rhs);
 	return *this;
@@ -813,7 +798,7 @@ namespace tr2
        *
        *  These should be self-explanatory.
        */
-      dynamic_bitset<_WordT, _Alloc>&
+      dynamic_bitset&
       operator<<=(size_type __pos)
       {
 	if (__builtin_expect(__pos < this->_M_Nb, 1))
@@ -826,7 +811,7 @@ namespace tr2
 	return *this;
       }
 
-      dynamic_bitset<_WordT, _Alloc>&
+      dynamic_bitset&
       operator>>=(size_type __pos)
       {
 	if (__builtin_expect(__pos < this->_M_Nb, 1))
@@ -844,7 +829,7 @@ namespace tr2
       /**
        *  @brief Sets every bit to true.
        */
-      dynamic_bitset<_WordT, _Alloc>&
+      dynamic_bitset&
       set()
       {
 	this->_M_do_set();
@@ -858,7 +843,7 @@ namespace tr2
        *  @param  __val  Either true or false, defaults to true.
        *  @throw  std::out_of_range  If @a __pos is bigger the size of the %set.
        */
-      dynamic_bitset<_WordT, _Alloc>&
+      dynamic_bitset&
       set(size_type __pos, bool __val = true)
       {
 	if (__pos >= _M_Nb)
@@ -869,7 +854,7 @@ namespace tr2
       /**
        *  @brief Sets every bit to false.
        */
-      dynamic_bitset<_WordT, _Alloc>&
+      dynamic_bitset&
       reset()
       {
 	this->_M_do_reset();
@@ -883,7 +868,7 @@ namespace tr2
        *
        *  Same as writing @c set(__pos, false).
        */
-      dynamic_bitset<_WordT, _Alloc>&
+      dynamic_bitset&
       reset(size_type __pos)
       {
 	if (__pos >= _M_Nb)
@@ -894,7 +879,7 @@ namespace tr2
       /**
        *  @brief Toggles every bit to its opposite value.
        */
-      dynamic_bitset<_WordT, _Alloc>&
+      dynamic_bitset&
       flip()
       {
 	this->_M_do_flip();
@@ -907,7 +892,7 @@ namespace tr2
        *  @param  __pos  The index of the bit.
        *  @throw  std::out_of_range  If @a __pos is bigger the size of the %set.
        */
-      dynamic_bitset<_WordT, _Alloc>&
+      dynamic_bitset&
       flip(size_type __pos)
       {
 	if (__pos >= _M_Nb)
@@ -916,7 +901,7 @@ namespace tr2
       }
 
       /// See the no-argument flip().
-      dynamic_bitset<_WordT, _Alloc>
+      dynamic_bitset
       operator~() const
       { return dynamic_bitset<_WordT, _Alloc>(*this).flip(); }
 
@@ -978,19 +963,23 @@ namespace tr2
 	}
 
       // Helper functions for string operations.
-      template<typename _CharT, typename _Traits>
+      template<typename _Traits = std::char_traits<char>,
+	       typename _CharT = typename _Traits::char_type>
 	void
 	_M_copy_from_ptr(const _CharT*, size_t, size_t, size_t,
-			 _CharT, _CharT);
+			 _CharT __zero = _CharT('0'),
+			 _CharT __one = _CharT('1'));
 
       template<typename _CharT, typename _Traits, typename _Alloc1>
 	void
-	_M_copy_from_string(const std::basic_string<_CharT,
-			    _Traits, _Alloc1>& __str, size_t __pos, size_t __n,
+	_M_copy_from_string(const basic_string<_CharT, _Traits, _Alloc1>& __str,
+			    size_t __pos, size_t __n,
 			    _CharT __zero = _CharT('0'),
 			    _CharT __one = _CharT('1'))
-	{ _M_copy_from_ptr<_CharT, _Traits>(__str.data(), __str.size(),
-					    __pos, __n, __zero, __one); }
+	{
+	  _M_copy_from_ptr<_Traits>(__str.data(), __str.size(), __pos, __n,
+				    __zero, __one);
+	}
 
       template<typename _CharT, typename _Traits, typename _Alloc1>
 	void
@@ -1065,13 +1054,13 @@ namespace tr2
 
       //@{
       /// Self-explanatory.
-      dynamic_bitset<_WordT, _Alloc>
+      dynamic_bitset
       operator<<(size_type __pos) const
-      { return dynamic_bitset<_WordT, _Alloc>(*this) <<= __pos; }
+      { return dynamic_bitset(*this) <<= __pos; }
 
-      dynamic_bitset<_WordT, _Alloc>
+      dynamic_bitset
       operator>>(size_type __pos) const
-      { return dynamic_bitset<_WordT, _Alloc>(*this) >>= __pos; }
+      { return dynamic_bitset(*this) >>= __pos; }
       //@}
 
       /**
@@ -1102,14 +1091,14 @@ namespace tr2
       { 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); }
+      operator==(const dynamic_bitset& __lhs,
+		 const dynamic_bitset& __rhs) noexcept
+      { return __lhs._M_Nb == __rhs._M_Nb && __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); }
+      operator<(const dynamic_bitset& __lhs,
+		const dynamic_bitset& __rhs) noexcept
+      { return __lhs._M_is_less(__rhs) || __lhs._M_Nb < __rhs._M_Nb; }
     };
 
   template<typename _WordT, typename _Alloc>
diff --git a/libstdc++-v3/include/tr2/dynamic_bitset.tcc b/libstdc++-v3/include/tr2/dynamic_bitset.tcc
index 8228d7b..bbd2cb3 100644
--- a/libstdc++-v3/include/tr2/dynamic_bitset.tcc
+++ b/libstdc++-v3/include/tr2/dynamic_bitset.tcc
@@ -174,7 +174,7 @@ namespace tr2
 
   // Definitions of non-inline member functions.
   template<typename _WordT, typename _Alloc>
-    template<typename _CharT, typename _Traits>
+    template<typename _Traits, typename _CharT>
       void
       dynamic_bitset<_WordT, _Alloc>::
       _M_copy_from_ptr(const _CharT* __str, size_t __len,
diff --git a/libstdc++-v3/testsuite/tr2/dynamic_bitset/cmp.cc b/libstdc++-v3/testsuite/tr2/dynamic_bitset/cmp.cc
new file mode 100644
index 0000000..a811307
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/dynamic_bitset/cmp.cc
@@ -0,0 +1,50 @@
+// Copyright (C) 2019 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/>.
+
+// { dg-do run { target c++11 } }
+
+#include <tr2/dynamic_bitset>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::tr2::dynamic_bitset<> a(100);
+  std::tr2::dynamic_bitset<> b = a;
+  VERIFY( a == b );
+  b.resize(99);
+  VERIFY( a != b );
+}
+
+void
+test02()
+{
+  std::tr2::dynamic_bitset<> a(100);
+  std::tr2::dynamic_bitset<> b = a;
+  VERIFY( !(a < b) );
+  VERIFY( !(b < a) );
+  b.resize(99);
+  VERIFY( !(a < b) );
+  VERIFY( b < a );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/tr2/dynamic_bitset/cons.cc b/libstdc++-v3/testsuite/tr2/dynamic_bitset/cons.cc
new file mode 100644
index 0000000..9e21a91
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/dynamic_bitset/cons.cc
@@ -0,0 +1,105 @@
+// Copyright (C) 2019 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/>.
+
+// { dg-do run { target c++11 } }
+
+#include <tr2/dynamic_bitset>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::tr2::dynamic_bitset<> a;
+  VERIFY( a.size() == 0 );
+  VERIFY( a.empty() );
+  std::tr2::dynamic_bitset<> b(1);
+  VERIFY( b.size() == 1 );
+  VERIFY( !b.empty() );
+  VERIFY( a != b );
+}
+
+void
+test02()
+{
+  std::tr2::dynamic_bitset<> a(1, 0); // { 0 }
+  std::tr2::dynamic_bitset<> b(2, 2); // { 0, 1 }
+  VERIFY( a != b );
+}
+
+void
+test03()
+{
+  std::tr2::dynamic_bitset<> a;
+  a.resize(1);                        // { 0 }
+  std::tr2::dynamic_bitset<> b(2, 2); // { 0, 1 }
+  VERIFY( a != b );
+}
+
+void
+test04()
+{
+  std::tr2::dynamic_bitset<> a(3, 2); // { 0, 1, 0 }
+  std::tr2::dynamic_bitset<> b(2, 2); // { 0, 1 }
+  VERIFY( a != b );
+}
+
+void
+test05()
+{
+  std::tr2::dynamic_bitset<unsigned short> a(1, 0); // { 0 }
+  std::tr2::dynamic_bitset<unsigned short> b(2, 2); // { 0, 1 }
+  VERIFY( a != b );
+}
+
+void
+test06()
+{
+  std::tr2::dynamic_bitset<unsigned short> a;
+  a.resize(1);                                      // { 0 }
+  std::tr2::dynamic_bitset<unsigned short> b(2, 2); // { 0, 1 }
+  VERIFY( a != b );
+}
+
+void
+test07()
+{
+  std::tr2::dynamic_bitset<unsigned short> a(3, 2); // { 0, 1, 0 }
+  std::tr2::dynamic_bitset<unsigned short> b(2, 2); // { 0, 1 }
+  VERIFY( a != b );
+}
+
+void
+test08()
+{
+  std::tr2::dynamic_bitset<> a(65, -1ULL);
+  std::tr2::dynamic_bitset<> b(64, -1ULL);
+  b.push_back(0);
+  VERIFY( a == b );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  test05();
+  test06();
+  test07();
+  test08();
+}
diff --git a/libstdc++-v3/testsuite/tr2/dynamic_bitset/copy.cc b/libstdc++-v3/testsuite/tr2/dynamic_bitset/copy.cc
new file mode 100644
index 0000000..06bc115
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/dynamic_bitset/copy.cc
@@ -0,0 +1,55 @@
+// Copyright (C) 2019 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/>.
+
+// { dg-do run { target c++11 } }
+
+#include <tr2/dynamic_bitset>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::tr2::dynamic_bitset<> a(100);
+  const auto n = a.num_blocks();
+  std::tr2::dynamic_bitset<> b = a;
+  VERIFY(b.num_blocks() == n);
+  VERIFY(b.size() == 100);
+  VERIFY(a.num_blocks() == n);
+  VERIFY(a.size() == 100);
+  VERIFY(b == a);
+}
+
+void
+test02()
+{
+  std::tr2::dynamic_bitset<> a(100);
+  const auto n = a.num_blocks();
+  std::tr2::dynamic_bitset<> b;
+  b = a;
+  VERIFY(b.num_blocks() == n);
+  VERIFY(b.size() == 100);
+  VERIFY(a.num_blocks() == n);
+  VERIFY(a.size() == 100);
+  VERIFY(b == a);
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/tr2/dynamic_bitset/move.cc b/libstdc++-v3/testsuite/tr2/dynamic_bitset/move.cc
new file mode 100644
index 0000000..ed320db
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/dynamic_bitset/move.cc
@@ -0,0 +1,53 @@
+// Copyright (C) 2019 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/>.
+
+// { dg-do run { target c++11 } }
+
+#include <tr2/dynamic_bitset>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::tr2::dynamic_bitset<> a(100);
+  const auto n = a.num_blocks();
+  std::tr2::dynamic_bitset<> b = std::move(a);
+  VERIFY(b.num_blocks() == n);
+  VERIFY(b.size() == 100);
+  VERIFY(a.num_blocks() == 0);
+  VERIFY(a.size() == 0);
+}
+
+void
+test02()
+{
+  std::tr2::dynamic_bitset<> a(100);
+  const auto n = a.num_blocks();
+  std::tr2::dynamic_bitset<> b;
+  b = std::move(a);
+  VERIFY(b.num_blocks() == n);
+  VERIFY(b.size() == 100);
+  VERIFY(a.num_blocks() == 0);
+  VERIFY(a.size() == 0);
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/tr2/dynamic_bitset/pr92059.cc b/libstdc++-v3/testsuite/tr2/dynamic_bitset/pr92059.cc
new file mode 100644
index 0000000..0aec1ad
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/dynamic_bitset/pr92059.cc
@@ -0,0 +1,36 @@
+// Copyright (C) 2019 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/>.
+
+// { dg-do run { target c++11 } }
+
+#include <tr2/dynamic_bitset>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  // PR libstdc++/92059
+  std::tr2::dynamic_bitset<> b1(10000), b2(10000);
+  b2 = b1; // crashed on missing return
+  VERIFY( b2 == b1);
+}
+
+int
+main()
+{
+  test01();
+}



More information about the Libstdc++-cvs mailing list