PR libstdc++/92059 fix several bugs in tr2::dynamic_bitset
authorJonathan Wakely <jwakely@redhat.com>
Fri, 11 Oct 2019 15:29:55 +0000 (16:29 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 11 Oct 2019 15:29:55 +0000 (16:29 +0100)
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: r276890

libstdc++-v3/ChangeLog
libstdc++-v3/include/tr2/dynamic_bitset
libstdc++-v3/include/tr2/dynamic_bitset.tcc
libstdc++-v3/testsuite/tr2/dynamic_bitset/cmp.cc [new file with mode: 0644]
libstdc++-v3/testsuite/tr2/dynamic_bitset/cons.cc [new file with mode: 0644]
libstdc++-v3/testsuite/tr2/dynamic_bitset/copy.cc [new file with mode: 0644]
libstdc++-v3/testsuite/tr2/dynamic_bitset/move.cc [new file with mode: 0644]
libstdc++-v3/testsuite/tr2/dynamic_bitset/pr92059.cc [new file with mode: 0644]

index 1459185de26fc52e411927725d5c266ee240b763..3e6a7ddb539b9739e3a51da67d526b5af0137190 100644 (file)
@@ -1,5 +1,41 @@
 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.
+
        * include/bits/charconv.h (__to_chars_len): Avoid -Wsign-compare
        warnings.
 
index 434a4cc87ec1c750974fa4e9273196483b1ccbb0..28c877c048422cd62f73dc81d553603ea2d71050 100644 (file)
 #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>
index 8228d7bc472651bb7a2cb12f7a689e02c41327ff..bbd2cb3bb045f633fbcc9a96fa582de961c3df4b 100644 (file)
@@ -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 (file)
index 0000000..a811307
--- /dev/null
@@ -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 (file)
index 0000000..9e21a91
--- /dev/null
@@ -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 (file)
index 0000000..06bc115
--- /dev/null
@@ -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 (file)
index 0000000..ed320db
--- /dev/null
@@ -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 (file)
index 0000000..0aec1ad
--- /dev/null
@@ -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();
+}