From patchwork Thu Sep 22 14:23:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 1372 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5044:0:0:0:0:0 with SMTP id h4csp225500wrt; Thu, 22 Sep 2022 07:26:07 -0700 (PDT) X-Google-Smtp-Source: AMsMyM76Etg4G52jeZTc+9+p1YBzlN49wfpcLJI7ZoxOE1mOZDBQ2924dOMz8pbEDZitt12dhuHj X-Received: by 2002:aa7:da83:0:b0:44e:69ba:81c7 with SMTP id q3-20020aa7da83000000b0044e69ba81c7mr3595701eds.323.1663856767517; Thu, 22 Sep 2022 07:26:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1663856767; cv=none; d=google.com; s=arc-20160816; b=vwVcVyXMuGtZmsFpCgpbVnxzbPVyln5iZQqxQbnIinaXKUAQlefj+h1Bv2T88LVWKx lf04hOQdqyzLkf/ratt/D+42vWmOsAd9e0XRiXSh/G3rrj99gfy+qKRoaeXtqownO0BT Mmtp7Ss1q8ur9wbSqfJXMQf47X0vG2NYDxKJZyn9ic8fXDxsC6UplsbuXLSvdAiZTH77 d5blKUeifAvl+WFvicryiy3kBC7V5OVKD70bkLgMbsPax026VMVxLy7wz7W51mCUQo7y W8e698A+EGIwZHA95+0k9Gl5k5jTCHk2cPL4ct61E6kjHaqLzNiD3JlJNPcQhjIcEvlO csNA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:dmarc-filter:delivered-to:dkim-signature :dkim-filter; bh=ZGhkhY5/L4IwytMzw0IGJ7I4hX8TzTYIFiLfKKw52fc=; b=dzgo0KYJzK8k81MPa65Sch3PfaqSXPPxxZNsKNEbCicKqI6phiD1cWH5EHgbx66B8P AfZDAIxrLqCTYf9UXIgNQFH4F/a8LWLOT7TECC869ulgwAY0AbPThyiRTlTL5f6QQiTb QIZ8/qIlJx+E4NkpGivX5pC07IbUdA4rnWhxBCQ6RpVzpZeasQ5rDyGloPb6jcoVCO8o abg0rWeUx3E63TkIEhD3tuSSPKBvlvlRuwYdB4BubNw9jpyKm26I0sWJl1kBI9yhrxMN 9B0FwivFFg/yB0O1oLhmZVfC7CbC5eqajHSDYe8Mx95qjD9vYLytOigiJ5jmz98y10DP Ceqg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=ItU4dQ0Z; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id f28-20020a50a6dc000000b004483b772d31si4944496edc.230.2022.09.22.07.26.07 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Sep 2022 07:26:07 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=ItU4dQ0Z; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B78F3385780A for ; Thu, 22 Sep 2022 14:26:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B78F3385780A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1663856765; bh=ZGhkhY5/L4IwytMzw0IGJ7I4hX8TzTYIFiLfKKw52fc=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=ItU4dQ0ZzFCvRvrmp9b7yPX0y9T1F2Vtz3jwQr8HGRXA4k/VrQ4eTK3yER9dwIYsu 3YEjSYZjnXe3GJDkmBzQ7+9Gls7qwdNm1Djar2zjkI2oWJ+4bWYaqj7I2iP+lTH/1o 9JVK6zTC3r4bVHRCbjT3JCQKohdij+K/J/X8Zy4M= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org 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 10F903857B9C for ; Thu, 22 Sep 2022 14:24:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 10F903857B9C 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) 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 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=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jonathan Wakely via Gcc-patches From: Jonathan Wakely Reply-To: Jonathan Wakely Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1744680274263688237?= X-GMAIL-MSGID: =?utf-8?q?1744680274263688237?= 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