From: Jonathan Wakely <jwakely@redhat.com>
To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: [committed 2/2] libstdc++: Implement constexpr std::bitset for C++23 (P2417R2)
Date: Thu, 22 Sep 2022 15:23:53 +0100 [thread overview]
Message-ID: <20220922142353.1139862-2-jwakely@redhat.com> (raw)
In-Reply-To: <20220922142353.1139862-1-jwakely@redhat.com>
Tested x86_64-linux. Pushed to trunk.
-- >8 --
Also add _GLIBCXX_HOSTED checks to simplify making <bitset>
freestanding in the near future.
libstdc++-v3/ChangeLog:
* include/std/bitset (bitset): Add constexpr for C++23. Guard
members using std::string with _GLIBCXX_HOSTED.
* include/std/version (__cpp_lib_constexpr_bitset): Define.
* testsuite/20_util/bitset/access/constexpr.cc: New test.
* testsuite/20_util/bitset/cons/constexpr_c++23.cc: New test.
* testsuite/20_util/bitset/count/constexpr.cc: New test.
* testsuite/20_util/bitset/ext/constexpr.cc: New test.
* testsuite/20_util/bitset/operations/constexpr_c++23.cc: New test.
* testsuite/20_util/bitset/version.cc: New test.
---
libstdc++-v3/include/std/bitset | 244 ++++++++++++------
libstdc++-v3/include/std/version | 1 +
.../20_util/bitset/access/constexpr.cc | 55 ++++
.../20_util/bitset/cons/constexpr_c++23.cc | 53 ++++
.../20_util/bitset/count/constexpr.cc | 93 +++++++
.../testsuite/20_util/bitset/ext/constexpr.cc | 32 +++
.../bitset/operations/constexpr_c++23.cc | 31 +++
.../testsuite/20_util/bitset/version.cc | 10 +
8 files changed, 440 insertions(+), 79 deletions(-)
create mode 100644 libstdc++-v3/testsuite/20_util/bitset/access/constexpr.cc
create mode 100644 libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc
create mode 100644 libstdc++-v3/testsuite/20_util/bitset/count/constexpr.cc
create mode 100644 libstdc++-v3/testsuite/20_util/bitset/ext/constexpr.cc
create mode 100644 libstdc++-v3/testsuite/20_util/bitset/operations/constexpr_c++23.cc
create mode 100644 libstdc++-v3/testsuite/20_util/bitset/version.cc
diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset
index 438c2f7efe9..0c84f15fda0 100644
--- a/libstdc++-v3/include/std/bitset
+++ b/libstdc++-v3/include/std/bitset
@@ -44,14 +44,15 @@
#pragma GCC system_header
-#include <string>
#include <bits/functexcept.h> // For invalid_argument, out_of_range,
// overflow_error
-#include <iosfwd>
-#include <bits/cxxabi_forced.h>
-
-#if __cplusplus >= 201103L
-# include <bits/functional_hash.h>
+#if _GLIBCXX_HOSTED
+# include <string>
+# include <iosfwd>
+# include <bits/cxxabi_forced.h>
+# if __cplusplus >= 201103L
+# include <bits/functional_hash.h>
+# endif
#endif
#define _GLIBCXX_BITSET_BITS_PER_WORD (__CHAR_BIT__ * __SIZEOF_LONG__)
@@ -65,6 +66,10 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
+#if __cplusplus > 202002L && _GLIBCXX_HOSTED
+# define __cpp_lib_constexpr_bitset 202202L
+#endif
+
/**
* Base class, general case. It is a class invariant that _Nw will be
* nonnegative.
@@ -111,7 +116,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT
{ return (static_cast<_WordT>(1)) << _S_whichbit(__pos); }
- _WordT&
+ _GLIBCXX14_CONSTEXPR _WordT&
_M_getword(size_t __pos) _GLIBCXX_NOEXCEPT
{ return _M_w[_S_whichword(__pos)]; }
@@ -120,12 +125,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ return _M_w[_S_whichword(__pos)]; }
#if __cplusplus >= 201103L
- const _WordT*
+ constexpr const _WordT*
_M_getdata() const noexcept
{ return _M_w; }
#endif
- _WordT&
+ _GLIBCXX23_CONSTEXPR _WordT&
_M_hiword() _GLIBCXX_NOEXCEPT
{ return _M_w[_Nw - 1]; }
@@ -133,52 +138,61 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_hiword() const _GLIBCXX_NOEXCEPT
{ return _M_w[_Nw - 1]; }
- void
+ _GLIBCXX23_CONSTEXPR void
_M_do_and(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT
{
for (size_t __i = 0; __i < _Nw; __i++)
_M_w[__i] &= __x._M_w[__i];
}
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_or(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT
{
for (size_t __i = 0; __i < _Nw; __i++)
_M_w[__i] |= __x._M_w[__i];
}
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_xor(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT
{
for (size_t __i = 0; __i < _Nw; __i++)
_M_w[__i] ^= __x._M_w[__i];
}
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT;
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT;
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_flip() _GLIBCXX_NOEXCEPT
{
for (size_t __i = 0; __i < _Nw; __i++)
_M_w[__i] = ~_M_w[__i];
}
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_set() _GLIBCXX_NOEXCEPT
{
for (size_t __i = 0; __i < _Nw; __i++)
_M_w[__i] = ~static_cast<_WordT>(0);
}
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_reset() _GLIBCXX_NOEXCEPT
- { __builtin_memset(_M_w, 0, _Nw * sizeof(_WordT)); }
+ {
+ if (__builtin_is_constant_evaluated())
+ {
+ for (_WordT& __w : _M_w)
+ __w = 0;
+ return;
+ }
- bool
+ __builtin_memset(_M_w, 0, _Nw * sizeof(_WordT));
+ }
+
+ _GLIBCXX14_CONSTEXPR bool
_M_is_equal(const _Base_bitset<_Nw>& __x) const _GLIBCXX_NOEXCEPT
{
for (size_t __i = 0; __i < _Nw; ++__i)
@@ -188,7 +202,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<size_t _Nb>
- bool
+ _GLIBCXX14_CONSTEXPR bool
_M_are_all() const _GLIBCXX_NOEXCEPT
{
for (size_t __i = 0; __i < _Nw - 1; __i++)
@@ -199,7 +213,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
- _Nb));
}
- bool
+ _GLIBCXX14_CONSTEXPR bool
_M_is_any() const _GLIBCXX_NOEXCEPT
{
for (size_t __i = 0; __i < _Nw; __i++)
@@ -208,7 +222,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return false;
}
- size_t
+ _GLIBCXX14_CONSTEXPR size_t
_M_do_count() const _GLIBCXX_NOEXCEPT
{
size_t __result = 0;
@@ -217,26 +231,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return __result;
}
- unsigned long
+ _GLIBCXX14_CONSTEXPR unsigned long
_M_do_to_ulong() const;
#if __cplusplus >= 201103L
- unsigned long long
+ _GLIBCXX14_CONSTEXPR unsigned long long
_M_do_to_ullong() const;
#endif
// find first "on" bit
- size_t
+ _GLIBCXX14_CONSTEXPR size_t
_M_do_find_first(size_t) const _GLIBCXX_NOEXCEPT;
// find the next "on" bit that follows "prev"
- size_t
+ _GLIBCXX14_CONSTEXPR size_t
_M_do_find_next(size_t, size_t) const _GLIBCXX_NOEXCEPT;
};
// Definitions of non-inline functions from _Base_bitset.
template<size_t _Nw>
- void
+ _GLIBCXX14_CONSTEXPR void
_Base_bitset<_Nw>::_M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT
{
if (__builtin_expect(__shift != 0, 1))
@@ -262,7 +276,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<size_t _Nw>
- void
+ _GLIBCXX14_CONSTEXPR void
_Base_bitset<_Nw>::_M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT
{
if (__builtin_expect(__shift != 0, 1))
@@ -289,7 +303,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<size_t _Nw>
- unsigned long
+ _GLIBCXX14_CONSTEXPR unsigned long
_Base_bitset<_Nw>::_M_do_to_ulong() const
{
for (size_t __i = 1; __i < _Nw; ++__i)
@@ -300,7 +314,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#if __cplusplus >= 201103L
template<size_t _Nw>
- unsigned long long
+ _GLIBCXX14_CONSTEXPR unsigned long long
_Base_bitset<_Nw>::_M_do_to_ullong() const
{
const bool __dw = sizeof(unsigned long long) > sizeof(unsigned long);
@@ -316,7 +330,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
#endif
template<size_t _Nw>
- size_t
+ _GLIBCXX14_CONSTEXPR size_t
_Base_bitset<_Nw>::
_M_do_find_first(size_t __not_found) const _GLIBCXX_NOEXCEPT
{
@@ -332,7 +346,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<size_t _Nw>
- size_t
+ _GLIBCXX14_CONSTEXPR size_t
_Base_bitset<_Nw>::
_M_do_find_next(size_t __prev, size_t __not_found) const _GLIBCXX_NOEXCEPT
{
@@ -406,7 +420,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT
{ return (static_cast<_WordT>(1)) << _S_whichbit(__pos); }
- _WordT&
+ _GLIBCXX14_CONSTEXPR _WordT&
_M_getword(size_t) _GLIBCXX_NOEXCEPT
{ return _M_w; }
@@ -415,12 +429,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ return _M_w; }
#if __cplusplus >= 201103L
- const _WordT*
+ constexpr const _WordT*
_M_getdata() const noexcept
{ return &_M_w; }
#endif
- _WordT&
+ _GLIBCXX14_CONSTEXPR _WordT&
_M_hiword() _GLIBCXX_NOEXCEPT
{ return _M_w; }
@@ -428,67 +442,67 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_hiword() const _GLIBCXX_NOEXCEPT
{ return _M_w; }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_and(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT
{ _M_w &= __x._M_w; }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_or(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT
{ _M_w |= __x._M_w; }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_xor(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT
{ _M_w ^= __x._M_w; }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT
{ _M_w <<= __shift; }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT
{ _M_w >>= __shift; }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_flip() _GLIBCXX_NOEXCEPT
{ _M_w = ~_M_w; }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_set() _GLIBCXX_NOEXCEPT
{ _M_w = ~static_cast<_WordT>(0); }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_reset() _GLIBCXX_NOEXCEPT
{ _M_w = 0; }
- bool
+ _GLIBCXX14_CONSTEXPR bool
_M_is_equal(const _Base_bitset<1>& __x) const _GLIBCXX_NOEXCEPT
{ return _M_w == __x._M_w; }
template<size_t _Nb>
- bool
+ _GLIBCXX14_CONSTEXPR bool
_M_are_all() const _GLIBCXX_NOEXCEPT
{ return _M_w == (~static_cast<_WordT>(0)
>> (_GLIBCXX_BITSET_BITS_PER_WORD - _Nb)); }
- bool
+ _GLIBCXX14_CONSTEXPR bool
_M_is_any() const _GLIBCXX_NOEXCEPT
{ return _M_w != 0; }
- size_t
+ _GLIBCXX14_CONSTEXPR size_t
_M_do_count() const _GLIBCXX_NOEXCEPT
{ return __builtin_popcountl(_M_w); }
- unsigned long
+ _GLIBCXX14_CONSTEXPR unsigned long
_M_do_to_ulong() const _GLIBCXX_NOEXCEPT
{ return _M_w; }
#if __cplusplus >= 201103L
- unsigned long long
+ constexpr unsigned long long
_M_do_to_ullong() const noexcept
{ return _M_w; }
#endif
- size_t
+ _GLIBCXX14_CONSTEXPR size_t
_M_do_find_first(size_t __not_found) const _GLIBCXX_NOEXCEPT
{
if (_M_w != 0)
@@ -498,7 +512,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
// find the next "on" bit that follows "prev"
- size_t
+ _GLIBCXX14_CONSTEXPR size_t
_M_do_find_next(size_t __prev, size_t __not_found) const
_GLIBCXX_NOEXCEPT
{
@@ -552,17 +566,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// This would normally give access to the data. The bounds-checking
// in the bitset class will prevent the user from getting this far,
- // but (1) it must still return an lvalue to compile, and (2) the
- // user might call _Unchecked_set directly, in which case this /needs/
- // to fail. Let's not penalize zero-length users unless they actually
+ // but this must fail if the user calls _Unchecked_set directly.
+ // Let's not penalize zero-length users unless they actually
// make an unchecked call; all the memory ugliness is therefore
// localized to this single should-never-get-this-far function.
+ __attribute__((__noreturn__))
_WordT&
_M_getword(size_t) _GLIBCXX_NOEXCEPT
- {
- __throw_out_of_range(__N("_Base_bitset::_M_getword"));
- return *new _WordT;
- }
+ { __throw_out_of_range(__N("_Base_bitset::_M_getword")); }
_GLIBCXX_CONSTEXPR _WordT
_M_getword(size_t) const _GLIBCXX_NOEXCEPT
@@ -572,75 +583,75 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_hiword() const _GLIBCXX_NOEXCEPT
{ return 0; }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_and(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT
{ }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_or(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT
{ }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_xor(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT
{ }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_left_shift(size_t) _GLIBCXX_NOEXCEPT
{ }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_right_shift(size_t) _GLIBCXX_NOEXCEPT
{ }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_flip() _GLIBCXX_NOEXCEPT
{ }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_set() _GLIBCXX_NOEXCEPT
{ }
- void
+ _GLIBCXX14_CONSTEXPR void
_M_do_reset() _GLIBCXX_NOEXCEPT
{ }
// Are all empty bitsets equal to each other? Are they equal to
// themselves? How to compare a thing which has no state? What is
// the sound of one zero-length bitset clapping?
- bool
+ _GLIBCXX_CONSTEXPR bool
_M_is_equal(const _Base_bitset<0>&) const _GLIBCXX_NOEXCEPT
{ return true; }
template<size_t _Nb>
- bool
+ _GLIBCXX_CONSTEXPR bool
_M_are_all() const _GLIBCXX_NOEXCEPT
{ return true; }
- bool
+ _GLIBCXX_CONSTEXPR bool
_M_is_any() const _GLIBCXX_NOEXCEPT
{ return false; }
- size_t
+ _GLIBCXX_CONSTEXPR size_t
_M_do_count() const _GLIBCXX_NOEXCEPT
{ return 0; }
- unsigned long
+ _GLIBCXX_CONSTEXPR unsigned long
_M_do_to_ulong() const _GLIBCXX_NOEXCEPT
{ return 0; }
#if __cplusplus >= 201103L
- unsigned long long
+ constexpr unsigned long long
_M_do_to_ullong() const noexcept
{ return 0; }
#endif
// Normally "not found" is the size, but that could also be
// misinterpreted as an index in this corner case. Oh well.
- size_t
+ _GLIBCXX_CONSTEXPR size_t
_M_do_find_first(size_t) const _GLIBCXX_NOEXCEPT
{ return 0; }
- size_t
+ _GLIBCXX_CONSTEXPR size_t
_M_do_find_next(size_t, size_t) const _GLIBCXX_NOEXCEPT
{ return 0; }
};
@@ -652,7 +663,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
typedef unsigned long _WordT;
- static void
+ static _GLIBCXX14_CONSTEXPR void
_S_do_sanitize(_WordT& __val) _GLIBCXX_NOEXCEPT
{ __val &= ~((~static_cast<_WordT>(0)) << _Extrabits); }
};
@@ -662,7 +673,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
typedef unsigned long _WordT;
- static void
+ static _GLIBCXX14_CONSTEXPR void
_S_do_sanitize(_WordT) _GLIBCXX_NOEXCEPT { }
};
@@ -755,7 +766,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> _Base;
typedef unsigned long _WordT;
+#if _GLIBCXX_HOSTED
template<class _CharT, class _Traits, class _Alloc>
+ _GLIBCXX23_CONSTEXPR
void
_M_check_initial_position(const std::basic_string<_CharT, _Traits, _Alloc>& __s,
size_t __position) const
@@ -766,7 +779,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
"(which is %zu)"),
__position, __s.size());
}
+#endif // HOSTED
+ _GLIBCXX23_CONSTEXPR
void _M_check(size_t __position, const char *__s) const
{
if (__position >= _Nb)
@@ -775,6 +790,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
__s, __position, _Nb);
}
+ _GLIBCXX23_CONSTEXPR
void
_M_do_sanitize() _GLIBCXX_NOEXCEPT
{
@@ -810,6 +826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
reference();
public:
+ _GLIBCXX23_CONSTEXPR
reference(bitset& __b, size_t __pos) _GLIBCXX_NOEXCEPT
{
_M_wp = &__b._M_getword(__pos);
@@ -820,10 +837,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
reference(const reference&) = default;
#endif
+#if __cplusplus > 202002L && __cpp_constexpr_dynamic_alloc
+ constexpr
+#endif
~reference() _GLIBCXX_NOEXCEPT
{ }
// For b[i] = __x;
+ _GLIBCXX23_CONSTEXPR
reference&
operator=(bool __x) _GLIBCXX_NOEXCEPT
{
@@ -835,6 +856,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
// For b[i] = b[__j];
+ _GLIBCXX23_CONSTEXPR
reference&
operator=(const reference& __j) _GLIBCXX_NOEXCEPT
{
@@ -846,15 +868,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
// Flips the bit
+ _GLIBCXX23_CONSTEXPR
bool
operator~() const _GLIBCXX_NOEXCEPT
{ return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) == 0; }
// For __x = b[i];
+ _GLIBCXX23_CONSTEXPR
operator bool() const _GLIBCXX_NOEXCEPT
{ return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) != 0; }
// For b[i].flip();
+ _GLIBCXX23_CONSTEXPR
reference&
flip() _GLIBCXX_NOEXCEPT
{
@@ -879,6 +904,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ _M_do_sanitize(); }
#endif
+#if _GLIBCXX_HOSTED
/**
* Use a subset of a string.
* @param __s A string of @a 0 and @a 1 characters.
@@ -889,6 +915,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* which is neither @a 0 nor @a 1.
*/
template<class _CharT, class _Traits, class _Alloc>
+ _GLIBCXX23_CONSTEXPR
explicit
bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __s,
size_t __position = 0)
@@ -911,6 +938,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* which is neither @a 0 nor @a 1.
*/
template<class _CharT, class _Traits, class _Alloc>
+ _GLIBCXX23_CONSTEXPR
bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __s,
size_t __position, size_t __n)
: _Base()
@@ -922,6 +950,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 396. what are characters zero and one.
template<class _CharT, class _Traits, class _Alloc>
+ _GLIBCXX23_CONSTEXPR
bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __s,
size_t __position, size_t __n,
_CharT __zero, _CharT __one = _CharT('1'))
@@ -942,6 +971,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* which is neither @a __zero nor @a __one.
*/
template<typename _CharT>
+ [[__gnu__::__nonnull__]]
+ _GLIBCXX23_CONSTEXPR
explicit
bitset(const _CharT* __str,
typename std::basic_string<_CharT>::size_type __n
@@ -958,7 +989,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
__n, __zero,
__one);
}
-#endif
+#endif // C++11
+#endif // HOSTED
// 23.3.5.2 bitset operations:
///@{
@@ -968,6 +1000,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*
* These should be self-explanatory.
*/
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
operator&=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT
{
@@ -975,6 +1008,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
operator|=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT
{
@@ -982,6 +1016,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
operator^=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT
{
@@ -997,6 +1032,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*
* These should be self-explanatory.
*/
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
operator<<=(size_t __position) _GLIBCXX_NOEXCEPT
{
@@ -1010,6 +1046,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
operator>>=(size_t __position) _GLIBCXX_NOEXCEPT
{
@@ -1030,6 +1067,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* extensions from the SGI version. They do no range checking.
* @ingroup SGIextensions
*/
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
_Unchecked_set(size_t __pos) _GLIBCXX_NOEXCEPT
{
@@ -1037,6 +1075,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
_Unchecked_set(size_t __pos, int __val) _GLIBCXX_NOEXCEPT
{
@@ -1047,6 +1086,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
_Unchecked_reset(size_t __pos) _GLIBCXX_NOEXCEPT
{
@@ -1054,6 +1094,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return *this;
}
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
_Unchecked_flip(size_t __pos) _GLIBCXX_NOEXCEPT
{
@@ -1071,6 +1112,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/**
* @brief Sets every bit to true.
*/
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
set() _GLIBCXX_NOEXCEPT
{
@@ -1085,6 +1127,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @param __val Either true or false, defaults to true.
* @throw std::out_of_range If @a pos is bigger the size of the %set.
*/
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
set(size_t __position, bool __val = true)
{
@@ -1095,6 +1138,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/**
* @brief Sets every bit to false.
*/
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
reset() _GLIBCXX_NOEXCEPT
{
@@ -1109,6 +1153,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
*
* Same as writing @c set(pos,false).
*/
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
reset(size_t __position)
{
@@ -1119,6 +1164,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/**
* @brief Toggles every bit to its opposite value.
*/
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
flip() _GLIBCXX_NOEXCEPT
{
@@ -1132,6 +1178,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @param __position The index of the bit.
* @throw std::out_of_range If @a pos is bigger the size of the %set.
*/
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>&
flip(size_t __position)
{
@@ -1140,6 +1187,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
/// See the no-argument flip().
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>
operator~() const _GLIBCXX_NOEXCEPT
{ return bitset<_Nb>(*this).flip(); }
@@ -1159,6 +1207,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* The DR has since been changed: range-checking is a precondition
* (users' responsibility), and these functions must not throw. -pme
*/
+ _GLIBCXX23_CONSTEXPR
reference
operator[](size_t __position)
{ return reference(*this, __position); }
@@ -1174,16 +1223,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @throw std::overflow_error If there are too many bits to be
* represented in an @c unsigned @c long.
*/
+ _GLIBCXX23_CONSTEXPR
unsigned long
to_ulong() const
{ return this->_M_do_to_ulong(); }
#if __cplusplus >= 201103L
+ _GLIBCXX23_CONSTEXPR
unsigned long long
to_ullong() const
{ return this->_M_do_to_ullong(); }
#endif
+#if _GLIBCXX_HOSTED
/**
* @brief Returns a character interpretation of the %bitset.
* @return The string equivalent of the bits.
@@ -1193,6 +1245,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* an example).
*/
template<class _CharT, class _Traits, class _Alloc>
+ _GLIBCXX23_CONSTEXPR
std::basic_string<_CharT, _Traits, _Alloc>
to_string() const
{
@@ -1204,6 +1257,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 396. what are characters zero and one.
template<class _CharT, class _Traits, class _Alloc>
+ _GLIBCXX23_CONSTEXPR
std::basic_string<_CharT, _Traits, _Alloc>
to_string(_CharT __zero, _CharT __one = _CharT('1')) const
{
@@ -1215,6 +1269,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 434. bitset::to_string() hard to use.
template<class _CharT, class _Traits>
+ _GLIBCXX23_CONSTEXPR
std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
to_string() const
{ return to_string<_CharT, _Traits, std::allocator<_CharT> >(); }
@@ -1222,12 +1277,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 853. to_string needs updating with zero and one.
template<class _CharT, class _Traits>
+ _GLIBCXX23_CONSTEXPR
std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
to_string(_CharT __zero, _CharT __one = _CharT('1')) const
{ return to_string<_CharT, _Traits,
std::allocator<_CharT> >(__zero, __one); }
template<class _CharT>
+ _GLIBCXX23_CONSTEXPR
std::basic_string<_CharT, std::char_traits<_CharT>,
std::allocator<_CharT> >
to_string() const
@@ -1237,6 +1294,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<class _CharT>
+ _GLIBCXX23_CONSTEXPR
std::basic_string<_CharT, std::char_traits<_CharT>,
std::allocator<_CharT> >
to_string(_CharT __zero, _CharT __one = _CharT('1')) const
@@ -1245,6 +1303,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::allocator<_CharT> >(__zero, __one);
}
+ _GLIBCXX23_CONSTEXPR
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
to_string() const
{
@@ -1252,6 +1311,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::allocator<char> >();
}
+ _GLIBCXX23_CONSTEXPR
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
to_string(char __zero, char __one = '1') const
{
@@ -1261,11 +1321,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// Helper functions for string operations.
template<class _CharT, class _Traits>
+ _GLIBCXX23_CONSTEXPR
void
_M_copy_from_ptr(const _CharT*, size_t, size_t, size_t,
_CharT, _CharT);
template<class _CharT, class _Traits, class _Alloc>
+ _GLIBCXX23_CONSTEXPR
void
_M_copy_from_string(const std::basic_string<_CharT,
_Traits, _Alloc>& __s, size_t __pos, size_t __n,
@@ -1274,23 +1336,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
__zero, __one); }
template<class _CharT, class _Traits, class _Alloc>
+ _GLIBCXX23_CONSTEXPR
void
_M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc>&,
_CharT, _CharT) const;
// NB: Backward compat.
template<class _CharT, class _Traits, class _Alloc>
+ _GLIBCXX23_CONSTEXPR
void
_M_copy_from_string(const std::basic_string<_CharT,
_Traits, _Alloc>& __s, size_t __pos, size_t __n)
{ _M_copy_from_string(__s, __pos, __n, _CharT('0'), _CharT('1')); }
template<class _CharT, class _Traits, class _Alloc>
+ _GLIBCXX23_CONSTEXPR
void
_M_copy_to_string(std::basic_string<_CharT, _Traits,_Alloc>& __s) const
{ _M_copy_to_string(__s, _CharT('0'), _CharT('1')); }
+#endif // HOSTED
/// Returns the number of bits which are set.
+ _GLIBCXX23_CONSTEXPR
size_t
count() const _GLIBCXX_NOEXCEPT
{ return this->_M_do_count(); }
@@ -1302,11 +1369,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
///@{
/// These comparisons for equality/inequality are, well, @e bitwise.
+ _GLIBCXX23_CONSTEXPR
bool
operator==(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT
{ return this->_M_is_equal(__rhs); }
#if __cpp_impl_three_way_comparison < 201907L
+ _GLIBCXX23_CONSTEXPR
bool
operator!=(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT
{ return !this->_M_is_equal(__rhs); }
@@ -1319,6 +1388,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @return The value at @a pos.
* @throw std::out_of_range If @a pos is bigger the size of the %set.
*/
+ _GLIBCXX23_CONSTEXPR
bool
test(size_t __position) const
{
@@ -1332,6 +1402,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @brief Tests whether all the bits are on.
* @return True if all the bits are set.
*/
+ _GLIBCXX23_CONSTEXPR
bool
all() const _GLIBCXX_NOEXCEPT
{ return this->template _M_are_all<_Nb>(); }
@@ -1340,6 +1411,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @brief Tests whether any of the bits are on.
* @return True if at least one bit is set.
*/
+ _GLIBCXX23_CONSTEXPR
bool
any() const _GLIBCXX_NOEXCEPT
{ return this->_M_is_any(); }
@@ -1348,16 +1420,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @brief Tests whether any of the bits are on.
* @return True if none of the bits are set.
*/
+ _GLIBCXX23_CONSTEXPR
bool
none() const _GLIBCXX_NOEXCEPT
{ return !this->_M_is_any(); }
///@{
/// Self-explanatory.
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>
operator<<(size_t __position) const _GLIBCXX_NOEXCEPT
{ return bitset<_Nb>(*this) <<= __position; }
+ _GLIBCXX23_CONSTEXPR
bitset<_Nb>
operator>>(size_t __position) const _GLIBCXX_NOEXCEPT
{ return bitset<_Nb>(*this) >>= __position; }
@@ -1369,6 +1444,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @ingroup SGIextensions
* @sa _Find_next
*/
+ _GLIBCXX23_CONSTEXPR
size_t
_Find_first() const _GLIBCXX_NOEXCEPT
{ return this->_M_do_find_first(_Nb); }
@@ -1380,14 +1456,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* @ingroup SGIextensions
* @sa _Find_first
*/
+ _GLIBCXX23_CONSTEXPR
size_t
_Find_next(size_t __prev) const _GLIBCXX_NOEXCEPT
{ return this->_M_do_find_next(__prev, _Nb); }
};
+#if _GLIBCXX_HOSTED
// Definitions of non-inline member functions.
template<size_t _Nb>
template<class _CharT, class _Traits>
+ _GLIBCXX23_CONSTEXPR
void
bitset<_Nb>::
_M_copy_from_ptr(const _CharT* __s, size_t __len,
@@ -1409,6 +1488,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<size_t _Nb>
template<class _CharT, class _Traits, class _Alloc>
+ _GLIBCXX23_CONSTEXPR
void
bitset<_Nb>::
_M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc>& __s,
@@ -1419,6 +1499,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (_Unchecked_test(__i - 1))
_Traits::assign(__s[_Nb - __i], __one);
}
+#endif // HOSTED
// 23.3.5.3 bitset operations:
///@{
@@ -1431,6 +1512,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
* These should be self-explanatory.
*/
template<size_t _Nb>
+ _GLIBCXX23_CONSTEXPR
inline bitset<_Nb>
operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT
{
@@ -1440,6 +1522,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template<size_t _Nb>
+ _GLIBCXX23_CONSTEXPR
inline bitset<_Nb>
operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT
{
@@ -1449,6 +1532,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
template <size_t _Nb>
+ _GLIBCXX23_CONSTEXPR
inline bitset<_Nb>
operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT
{
@@ -1458,6 +1542,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
///@}
+#if _GLIBCXX_HOSTED
///@{
/**
* @brief Global I/O operators for bitsets.
@@ -1549,6 +1634,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
return __os << __tmp;
}
///@}
+#endif // HOSTED
_GLIBCXX_END_NAMESPACE_CONTAINER
} // namespace std
@@ -1557,7 +1643,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
#undef _GLIBCXX_BITSET_BITS_PER_WORD
#undef _GLIBCXX_BITSET_BITS_PER_ULL
-#if __cplusplus >= 201103L
+#if __cplusplus >= 201103L && _GLIBCXX_HOSTED
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -1591,7 +1677,7 @@ _GLIBCXX_END_NAMESPACE_VERSION
#endif // C++11
-#ifdef _GLIBCXX_DEBUG
+#ifdef _GLIBCXX_DEBUG && _GLIBCXX_HOSTED
# include <debug/bitset>
#endif
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index 6b6187973a2..3fd5182d51d 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -309,6 +309,7 @@
#if _GLIBCXX_HOSTED
#define __cpp_lib_adaptor_iterator_pair_constructor 202106L
#if __cpp_constexpr_dynamic_alloc
+# define __cpp_lib_constexpr_bitset 202202L
# undef __cpp_lib_constexpr_memory
# define __cpp_lib_constexpr_memory 202202L
#endif
diff --git a/libstdc++-v3/testsuite/20_util/bitset/access/constexpr.cc b/libstdc++-v3/testsuite/20_util/bitset/access/constexpr.cc
new file mode 100644
index 00000000000..7c39fcadc6c
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bitset/access/constexpr.cc
@@ -0,0 +1,55 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do compile { target c++23 } }
+
+#include <bitset>
+#include <string>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_indexing()
+{
+ std::bitset<100> b("10010110");
+ VERIFY( b[0] == 0 );
+ VERIFY( b[1] == 1 );
+ const auto& cb = b;
+ VERIFY( cb[0] == 0 );
+ VERIFY( cb[1] == 1 );
+ b[1].flip();
+ VERIFY( cb[1] == 0 );
+ VERIFY( b[1] == 0 );
+ VERIFY( ~b[1] == 1 );
+ b[3] = true;
+ bool b3 = b[3];
+ VERIFY( b3 );
+ b[4] = b[3];
+ return true;
+}
+
+static_assert( test_indexing() );
+
+constexpr bool
+test_to_string()
+{
+ std::string str = "01101001";
+ return std::bitset<8>(str).to_string() == str;
+}
+
+static_assert( test_to_string() );
+
+constexpr bool
+test_to_ulong()
+{
+ unsigned long val = 0xcabba123;
+ return std::bitset<100>(val).to_ulong() == val;
+}
+
+static_assert( test_to_ulong() );
+
+constexpr bool
+test_to_ullong()
+{
+ unsigned long long val = 0x0123abcd0123abcd;
+ return std::bitset<100>(val).to_ullong() == val;
+}
+
+static_assert( test_to_ullong() );
diff --git a/libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc b/libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc
new file mode 100644
index 00000000000..92bfebe8f66
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bitset/cons/constexpr_c++23.cc
@@ -0,0 +1,53 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do compile { target c++23 } }
+
+#include <bitset>
+
+#ifndef __cpp_lib_constexpr_bitset
+# error "Feature-test macro for constexpr bitset missing in <bitset>"
+#elif __cpp_lib_constexpr_bitset != 202202L
+# error "Feature-test macro for constexpr bitset has wrong value in <bitset>"
+#endif
+
+#include <testsuite_hooks.h>
+
+constexpr bool test_ntbs()
+{
+ VERIFY( std::bitset<0>("000").all() );
+ VERIFY( std::bitset<0>("000", 2).all() );
+ VERIFY( std::bitset<1>("100", 2).all() );
+ VERIFY( std::bitset<1>("z00", 2, 'z').none() );
+ VERIFY( std::bitset<2>("ab0", 3, 'a', 'b').count() == 1 );
+
+ return true;
+}
+
+static_assert( test_ntbs() );
+
+constexpr bool test_string()
+{
+ using S = std::string;
+ VERIFY( std::bitset<0>(S("000")).all() );
+ VERIFY( std::bitset<1>(S("010"), 1, 2).all() );
+ VERIFY( std::bitset<2>(S("0110"), 1, 2).all() );
+ VERIFY( std::bitset<2>(S("1z110"), 1, 3, 'z').count() == 1 );
+ VERIFY( std::bitset<3>(S("0abab0"), 2, 3, 'a', 'b').count() == 2 );
+
+ return true;
+}
+
+static_assert( test_string() );
+
+constexpr bool test_wstring()
+{
+ using S = std::wstring;
+ VERIFY( std::bitset<0>(S(L"000")).all() );
+ VERIFY( std::bitset<1>(S(L"010"), 1, 2).all() );
+ VERIFY( std::bitset<2>(S(L"0110"), 1, 2).all() );
+ VERIFY( std::bitset<2>(S(L"1z110"), 1, 3, L'z').count() == 1 );
+ VERIFY( std::bitset<3>(S(L"0abab0"), 2, 3, L'a', L'b').count() == 2 );
+
+ return true;
+}
+
+static_assert( test_wstring() );
diff --git a/libstdc++-v3/testsuite/20_util/bitset/count/constexpr.cc b/libstdc++-v3/testsuite/20_util/bitset/count/constexpr.cc
new file mode 100644
index 00000000000..98f8e2259e1
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bitset/count/constexpr.cc
@@ -0,0 +1,93 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do compile { target c++23 } }
+
+#include <bitset>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_counting()
+{
+ auto check = []<std::size_t N>(const std::bitset<N>& bs) {
+ VERIFY( bs.size() == N );
+ unsigned count = 0;
+ for (unsigned n = 0; n < N; ++n)
+ if (bs.test(n))
+ ++count;
+ VERIFY( count == bs.count() );
+ VERIFY( bs.all() == (bs.count() == bs.size()) );
+ VERIFY( bs.any() == (bs.count() != 0) );
+ VERIFY( bs.none() == (bs.count() == 0) );
+ return true;
+ };
+
+ std::bitset<0> z0;
+ VERIFY( z0.count() == 0 );
+ VERIFY( check(z0) );
+ z0.set();
+ VERIFY( z0.count() == 0 );
+ VERIFY( check(z0) );
+
+ std::bitset<7> z7;
+ VERIFY( z7.count() == 0 );
+ VERIFY( check(z7) );
+ z7.set();
+ VERIFY( z7.count() == 7 );
+ VERIFY( check(z7) );
+ z7.flip(1);
+ VERIFY( z7.count() == 6 );
+ VERIFY( check(z7) );
+
+ std::bitset<31> z31;
+ VERIFY( z31.count() == 0 );
+ VERIFY( check(z31) );
+ z31.set();
+ VERIFY( z31.count() == 31 );
+ VERIFY( check(z31) );
+ z31.flip(1);
+ VERIFY( z31.count() == 30 );
+ VERIFY( check(z31) );
+
+ std::bitset<32> z32;
+ VERIFY( z32.count() == 0 );
+ VERIFY( check(z32) );
+ z32.set();
+ VERIFY( z32.count() == 32 );
+ VERIFY( check(z32) );
+ z32.flip(1);
+ VERIFY( z32.count() == 31 );
+ VERIFY( check(z32) );
+
+ std::bitset<63> z63;
+ VERIFY( z63.count() == 0 );
+ VERIFY( check(z63) );
+ z63.set();
+ VERIFY( z63.count() == 63 );
+ VERIFY( check(z63) );
+ z63.flip(1);
+ VERIFY( z63.count() == 62 );
+ VERIFY( check(z63) );
+
+ std::bitset<64> z64;
+ VERIFY( z64.count() == 0 );
+ VERIFY( check(z64) );
+ z64.set();
+ VERIFY( z64.count() == 64 );
+ VERIFY( check(z64) );
+ z64.flip(1);
+ VERIFY( z64.count() == 63 );
+ VERIFY( check(z64) );
+
+ std::bitset<1000> z1k;
+ VERIFY( z1k.count() == 0 );
+ VERIFY( check(z1k) );
+ z1k.set();
+ VERIFY( z1k.count() == 1000 );
+ VERIFY( check(z1k) );
+ z1k.flip(1);
+ VERIFY( z1k.count() == 999 );
+ VERIFY( check(z1k) );
+
+ return true;
+}
+
+static_assert( test_counting() );
diff --git a/libstdc++-v3/testsuite/20_util/bitset/ext/constexpr.cc b/libstdc++-v3/testsuite/20_util/bitset/ext/constexpr.cc
new file mode 100644
index 00000000000..f82e7aa409a
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bitset/ext/constexpr.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do compile { target c++23 } }
+
+#include <bitset>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test_find()
+{
+ VERIFY( std::bitset<0>()._Find_first() == 0 );
+ VERIFY( std::bitset<1>()._Find_first() == 1 );
+ VERIFY( std::bitset<55>("001000")._Find_first() == 3 );
+ VERIFY( std::bitset<66>("101000")._Find_next(3) == 5 );
+ return true;
+}
+
+static_assert( test_find() );
+
+constexpr bool
+test_unchecked()
+{
+ VERIFY( std::bitset<1>()._Unchecked_set(0).count() == 1 );
+ VERIFY( std::bitset<44>()._Unchecked_set(3).count() == 1 );
+ VERIFY( std::bitset<55>()._Unchecked_set(3, 0).count() == 0 );
+ VERIFY( std::bitset<66>()._Unchecked_set(3, 1).count() == 1 );
+ VERIFY( std::bitset<77>("111")._Unchecked_reset(1).count() == 2 );
+ VERIFY( std::bitset<88>("101")._Unchecked_flip(1).count() == 3 );
+ VERIFY( std::bitset<99>("010")._Unchecked_test(1) );
+ return true;
+}
+
+static_assert( test_unchecked() );
diff --git a/libstdc++-v3/testsuite/20_util/bitset/operations/constexpr_c++23.cc b/libstdc++-v3/testsuite/20_util/bitset/operations/constexpr_c++23.cc
new file mode 100644
index 00000000000..c594dd696a4
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bitset/operations/constexpr_c++23.cc
@@ -0,0 +1,31 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do compile { target c++23 } }
+
+#include <bitset>
+#include <testsuite_hooks.h>
+
+constexpr bool
+test()
+{
+ std::bitset<16> b0;
+ std::bitset<16> b1 = ~b0;
+ VERIFY( b1.all() );
+ b0 &= b1;
+ VERIFY( b0.none() );
+ b0 |= b1;
+ VERIFY( b0.all() );
+ b0 ^= b1;
+ VERIFY( b0.none() );
+ b0 = b1 << 8;
+ VERIFY( !b0.all() && !b0.none() );
+ VERIFY( ((b1 << 8) | (b1 >> 8)).all() );
+ b1 <<= 8;
+ b1 >>= 8;
+ b1 >>= 8;
+ VERIFY( b1.none() );
+ VERIFY( (~b1).all() );
+ VERIFY( b1.flip().all() );
+ return true;
+}
+
+static_assert( test() );
diff --git a/libstdc++-v3/testsuite/20_util/bitset/version.cc b/libstdc++-v3/testsuite/20_util/bitset/version.cc
new file mode 100644
index 00000000000..7197b1ed956
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bitset/version.cc
@@ -0,0 +1,10 @@
+// { dg-options "-std=gnu++23" }
+// { dg-do preprocess { target c++23 } }
+
+#include <version>
+
+#ifndef __cpp_lib_constexpr_bitset
+# error "Feature-test macro for constexpr bitset missing in <version>"
+#elif __cpp_lib_constexpr_bitset != 202202L
+# error "Feature-test macro for constexpr bitset has wrong value in <version>"
+#endif
--
2.37.3
next prev parent reply other threads:[~2022-09-22 14:24 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-09-22 14:23 [committed 1/2] libstdc++: Rearrange tests for <bitset> Jonathan Wakely
2022-09-22 14:23 ` Jonathan Wakely [this message]
2022-09-22 23:32 ` [committed 2/2] libstdc++: Implement constexpr std::bitset for C++23 (P2417R2) Jonathan Wakely
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220922142353.1139862-2-jwakely@redhat.com \
--to=jwakely@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=libstdc++@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).