Add a bitset constructor from string_view, with other arguments
matching the constructor from string. Test in ways that exercise
code paths not checked in existing tests for other constructors.
Fix existing tests that would fail to detect incorrect exception
behavior.

libstdc++-v3/ChangeLog:
        PR libstdc++/119742
        * include/bits/version.def: new preprocessor symbol
        * include/bits/version.h: new preprocessor symbol
        * include/std/bitset: new constructor
        * testsuite/20_util/bitset/cons/1.cc: fix
        * testsuite/20_util/bitset/cons/6282.cc: fix
        * testsuite/20_util/bitset/cons/string_view.cc: new tests
        * testsuite/20_util/bitset/cons/string_view_wide.cc: new tests
---
 libstdc++-v3/include/bits/version.def         |   8 ++
 libstdc++-v3/include/bits/version.h           |  10 ++
 libstdc++-v3/include/std/bitset               |  49 +++++++
 .../testsuite/20_util/bitset/cons/1.cc        |   1 +
 .../testsuite/20_util/bitset/cons/6282.cc     |   5 +-
 .../20_util/bitset/cons/string_view.cc        | 132 ++++++++++++++++++
 .../20_util/bitset/cons/string_view_wide.cc   |   8 ++
 7 files changed, 210 insertions(+), 3 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/20_util/bitset/cons/string_view.cc
 create mode 100644 
libstdc++-v3/testsuite/20_util/bitset/cons/string_view_wide.cc

diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index 880586e9126..d82585e1238 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -2012,6 +2012,14 @@ ftms = {
   };
 };
 
+ftms = {
+  name = bitset  // ...construct from string_view
+  values = {
+    v = 202306;
+    cxxmin = 26;
+  };
+};
+
 // Standard test specifications.
 stds[97] = ">= 199711L";
 stds[03] = ">= 199711L";
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index 4300adb2276..c0d3cbe623f 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2253,4 +2253,14 @@
 #endif /* !defined(__cpp_lib_sstream_from_string_view) && 
defined(__glibcxx_want_sstream_from_string_view) */
 #undef __glibcxx_want_sstream_from_string_view
 
+#if !defined(__cpp_lib_bitset)
+# if (__cplusplus >  202302L)
+#  define __glibcxx_bitset 202306L
+#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_bitset)
+#   define __cpp_lib_bitset 202306L
+#  endif
+# endif
+#endif /* !defined(__cpp_lib_bitset) && defined(__glibcxx_want_bitset) */
+#undef __glibcxx_bitset
+
 #undef __glibcxx_want_all
diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset
index 8b5d270c2a9..f4947902384 100644
--- a/libstdc++-v3/include/std/bitset
+++ b/libstdc++-v3/include/std/bitset
@@ -61,8 +61,13 @@
 #endif
 
 #define __glibcxx_want_constexpr_bitset
+#define __glibcxx_want_bitset  // ...construct from string_view
 #include <bits/version.h>
 
+#ifdef __cpp_lib_bitset // ...construct from string_view
+# include <string_view>
+#endif
+
 #define _GLIBCXX_BITSET_BITS_PER_WORD  (__CHAR_BIT__ * __SIZEOF_LONG__)
 #define _GLIBCXX_BITSET_WORDS(__n) \
   ((__n) / _GLIBCXX_BITSET_BITS_PER_WORD + \
@@ -831,6 +836,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 #endif // HOSTED
 
+#ifdef __cpp_lib_bitset
+      template<class _CharT, class _Traits>
+      constexpr void
+      _M_check_initial_position(
+       std::basic_string_view<_CharT, _Traits> __s,
+       typename std::basic_string_view<_CharT, _Traits>::size_type __position
+      ) const
+      {
+# if _GLIBCXX_HOSTED
+       if (__position > __s.size())
+         __throw_out_of_range_fmt(__N("bitset::bitset: __position "
+                                      "(which is %zu) > __s.size() "
+                                      "(which is %zu)"),
+                                  __position, __s.size());
+# endif
+      }
+#endif
+
       _GLIBCXX23_CONSTEXPR
       void _M_check(size_t __position, const char *__s) const
       {
@@ -1008,6 +1031,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        }
 #endif // HOSTED
 
+#ifdef __cpp_lib_bitset
+      /**
+       *  Use a subset of a string view.
+       *  @param  __s  A string_view of a sequence of @a 0 and @a 1 characters.
+       *  @param  __position  Index of the first character in @a __s to use.
+       *  @param  __n    The maximum number of characters from @a __s to use.
+       *  @throw std::out_of_range If @a __position is bigger the size
+       *  of @a __s.
+       *  @throw  std::invalid_argument  If a character appears in the string
+       *                                 which is neither @a 0 nor @a 1.
+       */
+      template<class _CharT, class _Traits>
+       constexpr explicit
+       bitset(std::basic_string_view<_CharT, _Traits> __s,
+         std::basic_string_view<_CharT, _Traits>::size_type __position = 0,
+         std::basic_string_view<_CharT, _Traits>::size_type __n =
+           std::basic_string_view<_CharT, _Traits>::npos,
+         _CharT __zero = _CharT('0'), _CharT __one = _CharT('1'))
+       : _Base()
+       {
+         _M_check_initial_position(__s, __position);
+         _M_copy_from_ptr<_CharT, _Traits>(
+           __s.data(), __s.size(), __position, __n, __zero, __one);
+       }
+#endif
+
 #if __cplusplus >= 201103L
       /**
        *  Construct from a character %array.
diff --git a/libstdc++-v3/testsuite/20_util/bitset/cons/1.cc 
b/libstdc++-v3/testsuite/20_util/bitset/cons/1.cc
index 0a40b6cd965..6441332c8d6 100644
--- a/libstdc++-v3/testsuite/20_util/bitset/cons/1.cc
+++ b/libstdc++-v3/testsuite/20_util/bitset/cons/1.cc
@@ -47,6 +47,7 @@ void test01(void)
   const size_t n3 = 128;
   try {
     std::bitset<n3> bit03(str01, 5);
+    VERIFY(false);
   }
   catch(std::invalid_argument& fail) {
     VERIFY( true );
diff --git a/libstdc++-v3/testsuite/20_util/bitset/cons/6282.cc 
b/libstdc++-v3/testsuite/20_util/bitset/cons/6282.cc
index fafa9fc808b..ee348c35b2a 100644
--- a/libstdc++-v3/testsuite/20_util/bitset/cons/6282.cc
+++ b/libstdc++-v3/testsuite/20_util/bitset/cons/6282.cc
@@ -39,6 +39,8 @@ void test02(void)
   std::bitset<0>  z3(std::string("10101010101"));
   VERIFY( z3.any() == false );
 
+  VERIFY( z1.to_ulong() == 0 );
+  VERIFY( (z1.to_string<char,char_traits<char>,allocator<char> >().empty() ));
   try {
     z1.set(0);
     VERIFY( false );
@@ -49,9 +51,6 @@ void test02(void)
   catch(...) {
     VERIFY( false );
   }
-
-  VERIFY( z1.to_ulong() == 0 );
-  VERIFY( (z1.to_string<char,char_traits<char>,allocator<char> >().empty() ));
 }
 
 int main()
diff --git a/libstdc++-v3/testsuite/20_util/bitset/cons/string_view.cc 
b/libstdc++-v3/testsuite/20_util/bitset/cons/string_view.cc
new file mode 100644
index 00000000000..ec3a6c86b68
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bitset/cons/string_view.cc
@@ -0,0 +1,132 @@
+// C++26 [bitset.cons]
+
+// { dg-do run { target c++26 } }
+
+#ifndef C
+# define C char
+# define L(s) s
+#endif
+
+#include <bitset>
+#include <string>
+#include <string_view>
+#include <algorithm> // std::reverse, std::transform
+#include <stdexcept>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  // template<_C,_T>
+  // constexpr explicit
+  // bitset(const basic_string_view<_C,_T>,
+  //   size_type pos, size_type n, _C zero, _C one)
+  try {
+    std::basic_string_view<C> str(L("stuff smith sessions"));
+    const std::size_t n = 128;
+    std::bitset<n> bit(str, 5);
+    VERIFY(false);
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( true );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  try {
+    std::basic_string_view<C> str(L("010101000011"));
+    const std::size_t n = 128;
+    const auto sz = str.size();
+    std::bitset<n> bit(str, 0);
+    std::basic_string<C> str02;
+    for (std::size_t i = 0; i < sz; ++i)
+      str02 += (bit.test(i) ? C('1') : C('0'));
+    std::reverse(str02.begin(), str02.end());
+    VERIFY( str02 == str );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( false );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  // substring<C> "010101000011"
+  //              "10100001"
+  try {
+    std::basic_string_view<C> str(L("010101000011"));
+    const std::size_t n = 128;
+    const auto sz = 8;
+    std::bitset<n> bit(str, 3, sz);
+    std::basic_string<C> str02;
+    for (std::size_t i = 0; i < sz; ++i)
+      str02 += (bit.test(i) ? C('1') : C('0'));
+    std::reverse(str02.begin(), str02.end());
+    VERIFY( str02 == str.substr(3, sz) );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( false );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  // "abababaaaabb", zero = 'a', one = 'b'
+  try {
+    std::basic_string_view<C> str(L("010101000011"));
+    const std::size_t n = 128;
+    const auto sz = str.size();
+    std::basic_string<C> str02(str);
+    std::transform(str02.cbegin(), str02.cend(), str02.begin(), [](auto c) {
+      return (c - C('0')) + C('a');
+    });
+    std::basic_string_view<C> str03(str02);
+    std::bitset<n> bit(str03, 0, 100, C('a'), C('b'));
+    std::basic_string<C> str04;
+    for (std::size_t i = 0; i < sz; ++i)
+      str04 += (bit.test(i) ? C('1') : C('0'));
+    std::reverse(str04.begin(), str04.end());
+    VERIFY( str04 == str );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( false );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  // "aba0aba", zero = 'a', one = 'b', '0' appears
+  try {
+    const std::size_t n = 128;
+    std::basic_string_view<C> str05(L("aba0aba"));
+    std::bitset<n> bit(str05, 0, 100, C('a'), C('b'));
+    VERIFY( false );
+  }
+  catch(std::invalid_argument& fail) {
+    VERIFY( true );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+
+  // pos > str.size()
+  try {
+    std::basic_string_view<C> str(L("010101000011"));
+    const std::size_t n = 128;
+    const auto sz = str.size();
+    std::bitset<n> bit(str, sz + 1, 100);
+    VERIFY( false );
+  }
+  catch(std::out_of_range& fail) {
+    VERIFY( true );
+  }
+  catch(...) {
+    VERIFY( false );
+  }
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/bitset/cons/string_view_wide.cc 
b/libstdc++-v3/testsuite/20_util/bitset/cons/string_view_wide.cc
new file mode 100644
index 00000000000..b53fe74a7ce
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bitset/cons/string_view_wide.cc
@@ -0,0 +1,8 @@
+// C++26 [bitset.cons]
+
+// { dg-do run { target c++26 } }
+
+#define C wchar_t
+#define L(s) L ## s
+
+#include "./string_view.cc"
-- 
2.49.0

Reply via email to