From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id DFED43857BA8 for ; Thu, 22 Sep 2022 14:24:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DFED43857BA8 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1663856646; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZGhkhY5/L4IwytMzw0IGJ7I4hX8TzTYIFiLfKKw52fc=; b=bPaIYaMWdTtoVjg0/8jCrkwoHBT0f9LcTY/k9XAfMRYXQfd2JV98GHdIwe96Hqi+PiFt4c iMi9tp/nSV9h+5uHWokVMR0bZsMZ6cE6dh4AJcAL8C3hXfc4YBrlRvmA2nc3G2J5nB21CN b8mLso3mPi43IsA05Z6Y5rHokN03hjA= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-134-JKnpzIgJPV-rEsgxWDT8-Q-1; Thu, 22 Sep 2022 10:23:56 -0400 X-MC-Unique: JKnpzIgJPV-rEsgxWDT8-Q-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 6052F858F17; Thu, 22 Sep 2022 14:23:55 +0000 (UTC) Received: from localhost (unknown [10.33.36.214]) by smtp.corp.redhat.com (Postfix) with ESMTP id E5C054B3FC7; Thu, 22 Sep 2022 14:23:54 +0000 (UTC) From: Jonathan Wakely 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 Message-Id: <20220922142353.1139862-2-jwakely@redhat.com> In-Reply-To: <20220922142353.1139862-1-jwakely@redhat.com> References: <20220922142353.1139862-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.9 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Tested x86_64-linux. Pushed to trunk. -- >8 -- Also add _GLIBCXX_HOSTED checks to simplify making 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 #include // For invalid_argument, out_of_range, // overflow_error -#include -#include - -#if __cplusplus >= 201103L -# include +#if _GLIBCXX_HOSTED +# include +# include +# include +# if __cplusplus >= 201103L +# include +# 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 - 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 - 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 - 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 - 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 - 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 + _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 + _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 - 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 - 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 + _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 + _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 + _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 + _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 + [[__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 + _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 + _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 + _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 + _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 + _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 + _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, std::allocator > to_string() const { @@ -1252,6 +1311,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER std::allocator >(); } + _GLIBCXX23_CONSTEXPR std::basic_string, std::allocator > to_string(char __zero, char __one = '1') const { @@ -1261,11 +1321,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Helper functions for string operations. template + _GLIBCXX23_CONSTEXPR void _M_copy_from_ptr(const _CharT*, size_t, size_t, size_t, _CharT, _CharT); template + _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 + _GLIBCXX23_CONSTEXPR void _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc>&, _CharT, _CharT) const; // NB: Backward compat. template + _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 + _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 template + _GLIBCXX23_CONSTEXPR void bitset<_Nb>:: _M_copy_from_ptr(const _CharT* __s, size_t __len, @@ -1409,6 +1488,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template template + _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 + _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 + _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 + _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 #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 +#include +#include + +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 + +#ifndef __cpp_lib_constexpr_bitset +# error "Feature-test macro for constexpr bitset missing in " +#elif __cpp_lib_constexpr_bitset != 202202L +# error "Feature-test macro for constexpr bitset has wrong value in " +#endif + +#include + +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 +#include + +constexpr bool +test_counting() +{ + auto check = [](const std::bitset& 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 +#include + +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 +#include + +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 + +#ifndef __cpp_lib_constexpr_bitset +# error "Feature-test macro for constexpr bitset missing in " +#elif __cpp_lib_constexpr_bitset != 202202L +# error "Feature-test macro for constexpr bitset has wrong value in " +#endif -- 2.37.3