Commit 07758d90 by Jonathan Wakely Committed by Jonathan Wakely

PR libstdc++/92059 fix several bugs in tr2::dynamic_bitset

	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
parent 2bf2dacb
2019-10-11 Jonathan Wakely <jwakely@redhat.com> 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 * include/bits/charconv.h (__to_chars_len): Avoid -Wsign-compare
warnings. warnings.
......
...@@ -34,10 +34,9 @@ ...@@ -34,10 +34,9 @@
#include <limits> #include <limits>
#include <vector> #include <vector>
#include <string> #include <string>
#include <memory> // For std::allocator #include <istream>
#include <bits/functexcept.h> // For invalid_argument, out_of_range, #include <bits/functexcept.h>
// overflow_error #include <bits/stl_algo.h> // For fill
#include <iosfwd>
#include <bits/cxxabi_forced.h> #include <bits/cxxabi_forced.h>
namespace std _GLIBCXX_VISIBILITY(default) namespace std _GLIBCXX_VISIBILITY(default)
...@@ -76,41 +75,48 @@ namespace tr2 ...@@ -76,41 +75,48 @@ namespace tr2
std::vector<block_type, allocator_type> _M_w; std::vector<block_type, allocator_type> _M_w;
explicit explicit
__dynamic_bitset_base(const allocator_type& __alloc = allocator_type()) __dynamic_bitset_base(const allocator_type& __alloc)
: _M_w(__alloc) : _M_w(__alloc)
{ } { }
explicit __dynamic_bitset_base() = default;
__dynamic_bitset_base(__dynamic_bitset_base&& __b) __dynamic_bitset_base(const __dynamic_bitset_base&) = default;
{ this->_M_w.swap(__b._M_w); } __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 explicit
__dynamic_bitset_base(size_type __nbits, unsigned long long __val = 0ULL, __dynamic_bitset_base(size_type __nbits, unsigned long long __val = 0ULL,
const allocator_type& __alloc = allocator_type()) const allocator_type& __alloc = allocator_type())
: _M_w(__nbits / _S_bits_per_block : _M_w(__nbits / _S_bits_per_block + (__nbits % _S_bits_per_block > 0),
+ (__nbits % _S_bits_per_block > 0), block_type(0), __alloc)
__val, __alloc)
{ {
unsigned long long __mask = ~static_cast<block_type>(0); if (__nbits < std::numeric_limits<decltype(__val)>::digits)
size_t __n = std::min(this->_M_w.size(), __val &= ~(-1ULL << __nbits);
sizeof(unsigned long long) / sizeof(block_type)); if (__val == 0)
for (size_t __i = 0; __i < __n; ++__i) 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); const size_t __n
__mask <<= _S_bits_per_block; = 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 void
_M_assign(const __dynamic_bitset_base& __b) _M_swap(__dynamic_bitset_base& __b) noexcept
{ this->_M_w = __b._M_w; }
void
_M_swap(__dynamic_bitset_base& __b)
{ this->_M_w.swap(__b._M_w); } { this->_M_w.swap(__b._M_w); }
void void
_M_clear() _M_clear() noexcept
{ this->_M_w.clear(); } { this->_M_w.clear(); }
void void
...@@ -129,7 +135,7 @@ namespace tr2 ...@@ -129,7 +135,7 @@ namespace tr2
} }
allocator_type allocator_type
_M_get_allocator() const _M_get_allocator() const noexcept
{ return this->_M_w.get_allocator(); } { return this->_M_w.get_allocator(); }
static size_type static size_type
...@@ -149,23 +155,23 @@ namespace tr2 ...@@ -149,23 +155,23 @@ namespace tr2
{ return (static_cast<block_type>(1)) << _S_whichbit(__pos); } { return (static_cast<block_type>(1)) << _S_whichbit(__pos); }
block_type& block_type&
_M_getword(size_type __pos) _M_getword(size_type __pos) noexcept
{ return this->_M_w[_S_whichword(__pos)]; } { return this->_M_w[_S_whichword(__pos)]; }
block_type block_type
_M_getword(size_type __pos) const _M_getword(size_type __pos) const noexcept
{ return this->_M_w[_S_whichword(__pos)]; } { return this->_M_w[_S_whichword(__pos)]; }
block_type& block_type&
_M_hiword() _M_hiword() noexcept
{ return this->_M_w[_M_w.size() - 1]; } { return this->_M_w[_M_w.size() - 1]; }
block_type block_type
_M_hiword() const _M_hiword() const noexcept
{ return this->_M_w[_M_w.size() - 1]; } { return this->_M_w[_M_w.size() - 1]; }
void 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()) if (__x._M_w.size() == this->_M_w.size())
for (size_t __i = 0; __i < this->_M_w.size(); ++__i) for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
...@@ -175,7 +181,7 @@ namespace tr2 ...@@ -175,7 +181,7 @@ namespace tr2
} }
void 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()) if (__x._M_w.size() == this->_M_w.size())
for (size_t __i = 0; __i < this->_M_w.size(); ++__i) for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
...@@ -185,7 +191,7 @@ namespace tr2 ...@@ -185,7 +191,7 @@ namespace tr2
} }
void 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()) if (__x._M_w.size() == this->_M_w.size())
for (size_t __i = 0; __i < this->_M_w.size(); ++__i) for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
...@@ -195,7 +201,7 @@ namespace tr2 ...@@ -195,7 +201,7 @@ namespace tr2
} }
void 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()) if (__x._M_w.size() == this->_M_w.size())
for (size_t __i = 0; __i < this->_M_w.size(); ++__i) for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
...@@ -211,28 +217,27 @@ namespace tr2 ...@@ -211,28 +217,27 @@ namespace tr2
_M_do_right_shift(size_t __shift); _M_do_right_shift(size_t __shift);
void void
_M_do_flip() _M_do_flip() noexcept
{ {
for (size_t __i = 0; __i < this->_M_w.size(); ++__i) for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
this->_M_w[__i] = ~this->_M_w[__i]; this->_M_w[__i] = ~this->_M_w[__i];
} }
void void
_M_do_set() _M_do_set() noexcept
{ {
for (size_t __i = 0; __i < this->_M_w.size(); ++__i) 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 void
_M_do_reset() _M_do_reset() noexcept
{ {
for (size_t __i = 0; __i < this->_M_w.size(); ++__i) std::fill(_M_w.begin(), _M_w.end(), static_cast<block_type>(0));
this->_M_w[__i] = static_cast<block_type>(0);
} }
bool 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()) if (__x._M_w.size() == this->_M_w.size())
{ {
...@@ -246,7 +251,7 @@ namespace tr2 ...@@ -246,7 +251,7 @@ namespace tr2
} }
bool 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()) if (__x._M_w.size() == this->_M_w.size())
{ {
...@@ -264,17 +269,17 @@ namespace tr2 ...@@ -264,17 +269,17 @@ namespace tr2
} }
size_t 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) 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 0;
return ((this->_M_w.size() - 1) * _S_bits_per_block return ((this->_M_w.size() - 1) * _S_bits_per_block
+ __builtin_popcountll(this->_M_hiword())); + __builtin_popcountll(this->_M_hiword()));
} }
bool bool
_M_is_any() const _M_is_any() const noexcept
{ {
for (size_t __i = 0; __i < this->_M_w.size(); ++__i) for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
if (this->_M_w[__i] != static_cast<block_type>(0)) if (this->_M_w[__i] != static_cast<block_type>(0))
...@@ -283,7 +288,7 @@ namespace tr2 ...@@ -283,7 +288,7 @@ namespace tr2
} }
bool 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()) if (__b._M_w.size() == this->_M_w.size())
{ {
...@@ -297,7 +302,7 @@ namespace tr2 ...@@ -297,7 +302,7 @@ namespace tr2
} }
bool 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)) if (this->is_subset_of(__b))
{ {
...@@ -311,7 +316,7 @@ namespace tr2 ...@@ -311,7 +316,7 @@ namespace tr2
} }
size_t size_t
_M_do_count() const _M_do_count() const noexcept
{ {
size_t __result = 0; size_t __result = 0;
for (size_t __i = 0; __i < this->_M_w.size(); ++__i) for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
...@@ -357,6 +362,7 @@ namespace tr2 ...@@ -357,6 +362,7 @@ namespace tr2
* *
* See N2050, * See N2050,
* Proposal to Add a Dynamically Sizeable Bitset to the Standard Library. * 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 * In the general unoptimized case, storage is allocated in
* word-sized blocks. Let B be the number of bits in a word, then * word-sized blocks. Let B be the number of bits in a word, then
...@@ -435,7 +441,7 @@ namespace tr2 ...@@ -435,7 +441,7 @@ namespace tr2
{ {
size_type __shift = this->_M_Nb % bits_per_block; size_type __shift = this->_M_Nb % bits_per_block;
if (__shift > 0) 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. // Set the unused bits in the uppermost word.
...@@ -444,22 +450,22 @@ namespace tr2 ...@@ -444,22 +450,22 @@ namespace tr2
{ {
size_type __shift = this->_M_Nb % bits_per_block; size_type __shift = this->_M_Nb % bits_per_block;
if (__shift > 0) 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 * These versions of single-bit set, reset, flip, and test
* do no range checking. * do no range checking.
*/ */
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
_M_unchecked_set(size_type __pos) _M_unchecked_set(size_type __pos) noexcept
{ {
this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); this->_M_getword(__pos) |= _Base::_S_maskbit(__pos);
return *this; return *this;
} }
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
_M_unchecked_set(size_type __pos, int __val) _M_unchecked_set(size_type __pos, int __val) noexcept
{ {
if (__val) if (__val)
this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); this->_M_getword(__pos) |= _Base::_S_maskbit(__pos);
...@@ -468,26 +474,26 @@ namespace tr2 ...@@ -468,26 +474,26 @@ namespace tr2
return *this; return *this;
} }
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
_M_unchecked_reset(size_type __pos) _M_unchecked_reset(size_type __pos) noexcept
{ {
this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos);
return *this; return *this;
} }
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
_M_unchecked_flip(size_type __pos) _M_unchecked_flip(size_type __pos) noexcept
{ {
this->_M_getword(__pos) ^= _Base::_S_maskbit(__pos); this->_M_getword(__pos) ^= _Base::_S_maskbit(__pos);
return *this; return *this;
} }
bool 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)) { return ((this->_M_getword(__pos) & _Base::_S_maskbit(__pos))
!= static_cast<_WordT>(0)); } != static_cast<_WordT>(0)); }
size_type _M_Nb; size_type _M_Nb = 0;
public: public:
/** /**
...@@ -511,22 +517,16 @@ namespace tr2 ...@@ -511,22 +517,16 @@ namespace tr2
block_type *_M_wp; block_type *_M_wp;
size_type _M_bpos; size_type _M_bpos;
// left undefined
reference();
public: 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_wp = &__b._M_getword(__pos);
this->_M_bpos = _Base::_S_whichbit(__pos); this->_M_bpos = _Base::_S_whichbit(__pos);
} }
~reference()
{ }
// For b[i] = __x; // For b[i] = __x;
reference& reference&
operator=(bool __x) operator=(bool __x) noexcept
{ {
if (__x) if (__x)
*this->_M_wp |= _Base::_S_maskbit(this->_M_bpos); *this->_M_wp |= _Base::_S_maskbit(this->_M_bpos);
...@@ -537,7 +537,7 @@ namespace tr2 ...@@ -537,7 +537,7 @@ namespace tr2
// For b[i] = b[__j]; // For b[i] = b[__j];
reference& reference&
operator=(const reference& __j) operator=(const reference& __j) noexcept
{ {
if ((*(__j._M_wp) & _Base::_S_maskbit(__j._M_bpos))) if ((*(__j._M_wp) & _Base::_S_maskbit(__j._M_bpos)))
*this->_M_wp |= _Base::_S_maskbit(this->_M_bpos); *this->_M_wp |= _Base::_S_maskbit(this->_M_bpos);
...@@ -548,16 +548,16 @@ namespace tr2 ...@@ -548,16 +548,16 @@ namespace tr2
// Flips the bit // Flips the bit
bool bool
operator~() const operator~() const noexcept
{ return (*(_M_wp) & _Base::_S_maskbit(this->_M_bpos)) == 0; } { return (*(_M_wp) & _Base::_S_maskbit(this->_M_bpos)) == 0; }
// For __x = b[i]; // For __x = b[i];
operator bool() const operator bool() const noexcept
{ return (*(this->_M_wp) & _Base::_S_maskbit(this->_M_bpos)) != 0; } { return (*(this->_M_wp) & _Base::_S_maskbit(this->_M_bpos)) != 0; }
// For b[i].flip(); // For b[i].flip();
reference& reference&
flip() flip() noexcept
{ {
*this->_M_wp ^= _Base::_S_maskbit(this->_M_bpos); *this->_M_wp ^= _Base::_S_maskbit(this->_M_bpos);
return *this; return *this;
...@@ -569,10 +569,14 @@ namespace tr2 ...@@ -569,10 +569,14 @@ namespace tr2
typedef bool const_reference; typedef bool const_reference;
// 23.3.5.1 constructors: // 23.3.5.1 constructors:
/// All bits set to zero.
dynamic_bitset() = default;
/// All bits set to zero. /// All bits set to zero.
explicit explicit
dynamic_bitset(const allocator_type& __alloc = allocator_type()) dynamic_bitset(const allocator_type& __alloc)
: _Base(__alloc), _M_Nb(0) : _Base(__alloc)
{ } { }
/// Initial bits bitwise-copied from a single word (others set to zero). /// Initial bits bitwise-copied from a single word (others set to zero).
...@@ -585,7 +589,7 @@ namespace tr2 ...@@ -585,7 +589,7 @@ namespace tr2
dynamic_bitset(initializer_list<block_type> __il, dynamic_bitset(initializer_list<block_type> __il,
const allocator_type& __alloc = allocator_type()) const allocator_type& __alloc = allocator_type())
: _Base(__alloc), _M_Nb(0) : _Base(__alloc)
{ this->append(__il); } { this->append(__il); }
/** /**
...@@ -609,8 +613,7 @@ namespace tr2 ...@@ -609,8 +613,7 @@ namespace tr2
__n = std::basic_string<_CharT, _Traits, _Alloc1>::npos, __n = std::basic_string<_CharT, _Traits, _Alloc1>::npos,
_CharT __zero = _CharT('0'), _CharT __one = _CharT('1'), _CharT __zero = _CharT('0'), _CharT __one = _CharT('1'),
const allocator_type& __alloc = allocator_type()) const allocator_type& __alloc = allocator_type())
: _Base(__alloc), : _Base(__alloc)
_M_Nb(0) // Watch for npos.
{ {
if (__pos > __str.size()) if (__pos > __str.size())
__throw_out_of_range(__N("dynamic_bitset::bitset initial position " __throw_out_of_range(__N("dynamic_bitset::bitset initial position "
...@@ -619,8 +622,7 @@ namespace tr2 ...@@ -619,8 +622,7 @@ namespace tr2
// Watch for npos. // Watch for npos.
this->_M_Nb = (__n > __str.size() ? __str.size() - __pos : __n); this->_M_Nb = (__n > __str.size() ? __str.size() - __pos : __n);
this->resize(this->_M_Nb); this->resize(this->_M_Nb);
this->_M_copy_from_string(__str, __pos, __n, this->_M_copy_from_string(__str, __pos, __n);
_CharT('0'), _CharT('1'));
} }
/** /**
...@@ -633,61 +635,42 @@ namespace tr2 ...@@ -633,61 +635,42 @@ namespace tr2
explicit explicit
dynamic_bitset(const char* __str, dynamic_bitset(const char* __str,
const allocator_type& __alloc = allocator_type()) const allocator_type& __alloc = allocator_type())
: _Base(__alloc) : _Base(__builtin_strlen(__str), 0ULL, __alloc),
_M_Nb(__builtin_strlen(__str))
{ {
size_t __len = 0; this->_M_copy_from_ptr(__str, _M_Nb, 0, _M_Nb);
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');
} }
/** /// Copy constructor.
* @brief Copy constructor. dynamic_bitset(const dynamic_bitset&) = default;
*/
dynamic_bitset(const dynamic_bitset& __b)
: _Base(__b), _M_Nb(__b.size())
{ }
/** /// Move constructor.
* @brief Move constructor. dynamic_bitset(dynamic_bitset&& __b) noexcept
*/ : _Base(std::move(__b)), _M_Nb(__b._M_Nb)
dynamic_bitset(dynamic_bitset&& __b) { __b.clear(); }
: _Base(std::forward<_Base>(__b)), _M_Nb(__b.size())
{ }
/** /// Swap with another bitset.
* @brief Swap with another bitset.
*/
void void
swap(dynamic_bitset& __b) swap(dynamic_bitset& __b) noexcept
{ {
this->_M_swap(__b); this->_M_swap(__b);
std::swap(this->_M_Nb, __b._M_Nb); std::swap(this->_M_Nb, __b._M_Nb);
} }
/** /// Copy assignment operator.
* @brief Assignment. dynamic_bitset& operator=(const dynamic_bitset&) = default;
*/
dynamic_bitset&
operator=(const dynamic_bitset& __b)
{
if (&__b != this)
{
this->_M_assign(__b);
this->_M_Nb = __b._M_Nb;
}
}
/** /// Move assignment operator.
* @brief Move assignment.
*/
dynamic_bitset& dynamic_bitset&
operator=(dynamic_bitset&& __b) 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; return *this;
} }
...@@ -695,7 +678,7 @@ namespace tr2 ...@@ -695,7 +678,7 @@ namespace tr2
* @brief Return the allocator for the bitset. * @brief Return the allocator for the bitset.
*/ */
allocator_type allocator_type
get_allocator() const get_allocator() const noexcept
{ return this->_M_get_allocator(); } { return this->_M_get_allocator(); }
/** /**
...@@ -734,6 +717,8 @@ namespace tr2 ...@@ -734,6 +717,8 @@ namespace tr2
++this->_M_Nb; ++this->_M_Nb;
} }
// XXX why is there no pop_back() member in the proposal?
/** /**
* @brief Append a block. * @brief Append a block.
*/ */
...@@ -770,36 +755,36 @@ namespace tr2 ...@@ -770,36 +755,36 @@ namespace tr2
* *
* These should be self-explanatory. * These should be self-explanatory.
*/ */
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
operator&=(const dynamic_bitset<_WordT, _Alloc>& __rhs) operator&=(const dynamic_bitset& __rhs)
{ {
this->_M_do_and(__rhs); this->_M_do_and(__rhs);
return *this; return *this;
} }
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
operator&=(dynamic_bitset<_WordT, _Alloc>&& __rhs) operator&=(dynamic_bitset&& __rhs)
{ {
this->_M_do_and(std::move(__rhs)); this->_M_do_and(std::move(__rhs));
return *this; return *this;
} }
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
operator|=(const dynamic_bitset<_WordT, _Alloc>& __rhs) operator|=(const dynamic_bitset& __rhs)
{ {
this->_M_do_or(__rhs); this->_M_do_or(__rhs);
return *this; return *this;
} }
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
operator^=(const dynamic_bitset<_WordT, _Alloc>& __rhs) operator^=(const dynamic_bitset& __rhs)
{ {
this->_M_do_xor(__rhs); this->_M_do_xor(__rhs);
return *this; return *this;
} }
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
operator-=(const dynamic_bitset<_WordT, _Alloc>& __rhs) operator-=(const dynamic_bitset& __rhs)
{ {
this->_M_do_dif(__rhs); this->_M_do_dif(__rhs);
return *this; return *this;
...@@ -813,7 +798,7 @@ namespace tr2 ...@@ -813,7 +798,7 @@ namespace tr2
* *
* These should be self-explanatory. * These should be self-explanatory.
*/ */
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
operator<<=(size_type __pos) operator<<=(size_type __pos)
{ {
if (__builtin_expect(__pos < this->_M_Nb, 1)) if (__builtin_expect(__pos < this->_M_Nb, 1))
...@@ -826,7 +811,7 @@ namespace tr2 ...@@ -826,7 +811,7 @@ namespace tr2
return *this; return *this;
} }
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
operator>>=(size_type __pos) operator>>=(size_type __pos)
{ {
if (__builtin_expect(__pos < this->_M_Nb, 1)) if (__builtin_expect(__pos < this->_M_Nb, 1))
...@@ -844,7 +829,7 @@ namespace tr2 ...@@ -844,7 +829,7 @@ namespace tr2
/** /**
* @brief Sets every bit to true. * @brief Sets every bit to true.
*/ */
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
set() set()
{ {
this->_M_do_set(); this->_M_do_set();
...@@ -858,7 +843,7 @@ namespace tr2 ...@@ -858,7 +843,7 @@ namespace tr2
* @param __val Either true or false, defaults to true. * @param __val Either true or false, defaults to true.
* @throw std::out_of_range If @a __pos is bigger the size of the %set. * @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) set(size_type __pos, bool __val = true)
{ {
if (__pos >= _M_Nb) if (__pos >= _M_Nb)
...@@ -869,7 +854,7 @@ namespace tr2 ...@@ -869,7 +854,7 @@ namespace tr2
/** /**
* @brief Sets every bit to false. * @brief Sets every bit to false.
*/ */
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
reset() reset()
{ {
this->_M_do_reset(); this->_M_do_reset();
...@@ -883,7 +868,7 @@ namespace tr2 ...@@ -883,7 +868,7 @@ namespace tr2
* *
* Same as writing @c set(__pos, false). * Same as writing @c set(__pos, false).
*/ */
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
reset(size_type __pos) reset(size_type __pos)
{ {
if (__pos >= _M_Nb) if (__pos >= _M_Nb)
...@@ -894,7 +879,7 @@ namespace tr2 ...@@ -894,7 +879,7 @@ namespace tr2
/** /**
* @brief Toggles every bit to its opposite value. * @brief Toggles every bit to its opposite value.
*/ */
dynamic_bitset<_WordT, _Alloc>& dynamic_bitset&
flip() flip()
{ {
this->_M_do_flip(); this->_M_do_flip();
...@@ -907,7 +892,7 @@ namespace tr2 ...@@ -907,7 +892,7 @@ namespace tr2
* @param __pos The index of the bit. * @param __pos The index of the bit.
* @throw std::out_of_range If @a __pos is bigger the size of the %set. * @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) flip(size_type __pos)
{ {
if (__pos >= _M_Nb) if (__pos >= _M_Nb)
...@@ -916,7 +901,7 @@ namespace tr2 ...@@ -916,7 +901,7 @@ namespace tr2
} }
/// See the no-argument flip(). /// See the no-argument flip().
dynamic_bitset<_WordT, _Alloc> dynamic_bitset
operator~() const operator~() const
{ return dynamic_bitset<_WordT, _Alloc>(*this).flip(); } { return dynamic_bitset<_WordT, _Alloc>(*this).flip(); }
...@@ -978,19 +963,23 @@ namespace tr2 ...@@ -978,19 +963,23 @@ namespace tr2
} }
// Helper functions for string operations. // Helper functions for string operations.
template<typename _CharT, typename _Traits> template<typename _Traits = std::char_traits<char>,
typename _CharT = typename _Traits::char_type>
void void
_M_copy_from_ptr(const _CharT*, size_t, size_t, size_t, _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> template<typename _CharT, typename _Traits, typename _Alloc1>
void void
_M_copy_from_string(const std::basic_string<_CharT, _M_copy_from_string(const basic_string<_CharT, _Traits, _Alloc1>& __str,
_Traits, _Alloc1>& __str, size_t __pos, size_t __n, size_t __pos, size_t __n,
_CharT __zero = _CharT('0'), _CharT __zero = _CharT('0'),
_CharT __one = _CharT('1')) _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> template<typename _CharT, typename _Traits, typename _Alloc1>
void void
...@@ -1065,13 +1054,13 @@ namespace tr2 ...@@ -1065,13 +1054,13 @@ namespace tr2
//@{ //@{
/// Self-explanatory. /// Self-explanatory.
dynamic_bitset<_WordT, _Alloc> dynamic_bitset
operator<<(size_type __pos) const 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 operator>>(size_type __pos) const
{ return dynamic_bitset<_WordT, _Alloc>(*this) >>= __pos; } { return dynamic_bitset(*this) >>= __pos; }
//@} //@}
/** /**
...@@ -1102,14 +1091,14 @@ namespace tr2 ...@@ -1102,14 +1091,14 @@ namespace tr2
{ return this->_M_is_proper_subset_of(__b); } { return this->_M_is_proper_subset_of(__b); }
friend bool friend bool
operator==(const dynamic_bitset<_WordT, _Alloc>& __lhs, operator==(const dynamic_bitset& __lhs,
const dynamic_bitset<_WordT, _Alloc>& __rhs) const dynamic_bitset& __rhs) noexcept
{ return __lhs._M_is_equal(__rhs); } { return __lhs._M_Nb == __rhs._M_Nb && __lhs._M_is_equal(__rhs); }
friend bool friend bool
operator<(const dynamic_bitset<_WordT, _Alloc>& __lhs, operator<(const dynamic_bitset& __lhs,
const dynamic_bitset<_WordT, _Alloc>& __rhs) const dynamic_bitset& __rhs) noexcept
{ return __lhs._M_is_less(__rhs); } { return __lhs._M_is_less(__rhs) || __lhs._M_Nb < __rhs._M_Nb; }
}; };
template<typename _WordT, typename _Alloc> template<typename _WordT, typename _Alloc>
......
...@@ -174,7 +174,7 @@ namespace tr2 ...@@ -174,7 +174,7 @@ namespace tr2
// Definitions of non-inline member functions. // Definitions of non-inline member functions.
template<typename _WordT, typename _Alloc> template<typename _WordT, typename _Alloc>
template<typename _CharT, typename _Traits> template<typename _Traits, typename _CharT>
void void
dynamic_bitset<_WordT, _Alloc>:: dynamic_bitset<_WordT, _Alloc>::
_M_copy_from_ptr(const _CharT* __str, size_t __len, _M_copy_from_ptr(const _CharT* __str, size_t __len,
......
// 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();
}
// 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();
}
// 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();
}
// 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();
}
// 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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment