From 07758d90c7bc6b80b10a83bac52f9ab9e394131d Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 11 Oct 2019 16:29:55 +0100 Subject: [PATCH] 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 --- libstdc++-v3/ChangeLog | 36 +++ libstdc++-v3/include/tr2/dynamic_bitset | 295 +++++++++--------- libstdc++-v3/include/tr2/dynamic_bitset.tcc | 2 +- .../testsuite/tr2/dynamic_bitset/cmp.cc | 50 +++ .../testsuite/tr2/dynamic_bitset/cons.cc | 105 +++++++ .../testsuite/tr2/dynamic_bitset/copy.cc | 55 ++++ .../testsuite/tr2/dynamic_bitset/move.cc | 53 ++++ .../testsuite/tr2/dynamic_bitset/pr92059.cc | 36 +++ 8 files changed, 478 insertions(+), 154 deletions(-) create mode 100644 libstdc++-v3/testsuite/tr2/dynamic_bitset/cmp.cc create mode 100644 libstdc++-v3/testsuite/tr2/dynamic_bitset/cons.cc create mode 100644 libstdc++-v3/testsuite/tr2/dynamic_bitset/copy.cc create mode 100644 libstdc++-v3/testsuite/tr2/dynamic_bitset/move.cc create mode 100644 libstdc++-v3/testsuite/tr2/dynamic_bitset/pr92059.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 1459185de26..3e6a7ddb539 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,41 @@ 2019-10-11 Jonathan Wakely + 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. diff --git a/libstdc++-v3/include/tr2/dynamic_bitset b/libstdc++-v3/include/tr2/dynamic_bitset index 434a4cc87ec..28c877c0484 100644 --- a/libstdc++-v3/include/tr2/dynamic_bitset +++ b/libstdc++-v3/include/tr2/dynamic_bitset @@ -34,10 +34,9 @@ #include #include #include -#include // For std::allocator -#include // For invalid_argument, out_of_range, - // overflow_error -#include +#include +#include +#include // For fill #include namespace std _GLIBCXX_VISIBILITY(default) @@ -76,41 +75,48 @@ namespace tr2 std::vector _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(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::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(__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(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(0); + this->_M_w[__i] = static_cast(-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(0); + std::fill(_M_w.begin(), _M_w.end(), static_cast(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(0)) + if (_M_w[__i] != static_cast(-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(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(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(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 __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> - (__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 + template, + 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 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 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 diff --git a/libstdc++-v3/include/tr2/dynamic_bitset.tcc b/libstdc++-v3/include/tr2/dynamic_bitset.tcc index 8228d7bc472..bbd2cb3bb04 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 - template + template 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 00000000000..a811307c73a --- /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 +// . + +// { dg-do run { target c++11 } } + +#include +#include + +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 00000000000..9e21a91ff52 --- /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 +// . + +// { dg-do run { target c++11 } } + +#include +#include + +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 a(1, 0); // { 0 } + std::tr2::dynamic_bitset b(2, 2); // { 0, 1 } + VERIFY( a != b ); +} + +void +test06() +{ + std::tr2::dynamic_bitset a; + a.resize(1); // { 0 } + std::tr2::dynamic_bitset b(2, 2); // { 0, 1 } + VERIFY( a != b ); +} + +void +test07() +{ + std::tr2::dynamic_bitset a(3, 2); // { 0, 1, 0 } + std::tr2::dynamic_bitset 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 00000000000..06bc1158a82 --- /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 +// . + +// { dg-do run { target c++11 } } + +#include +#include + +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 00000000000..ed320db300d --- /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 +// . + +// { dg-do run { target c++11 } } + +#include +#include + +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 00000000000..0aec1adf65b --- /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 +// . + +// { dg-do run { target c++11 } } + +#include +#include + +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(); +} -- 2.30.2