[libcxx-commits] [libcxx] [libc++] Implement LWG4294: bitset(const CharT*) constructor needs to be constrained (PR #238119)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Nov 2 13:54:00 PST 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: anant (antcybersec)

<details>
<summary>Changes</summary>

LWG4294 constrains bitset's `const charT*` constructor to char-like types. While libc++ already checked `_IsCharLikeType`, the trait was missing the non-array requirement from [strings.general].

Because of this, checking `std::is_constructible<std::bitset<N>, const char(*)[2]>` hit a hard compile error inside `basic_string` instead of evaluating to false.

This adds the missing `!is_array` check to `_IsCharLikeType`, adds a test covering the constraints, and updates Cxx26Issues.csv.

Fixes #<!-- -->171336

---
Full diff: https://github.com/llvm/llvm-project/pull/238119.diff


3 Files Affected:

- (modified) libcxx/docs/Status/Cxx26Issues.csv (+1-1) 
- (modified) libcxx/include/__type_traits/is_char_like_type.h (+8-1) 
- (added) libcxx/test/std/utilities/template.bitset/bitset.cons/char_ptr_ctor_constraints.compile.pass.cpp (+80) 


``````````diff
diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index 631486ed5af4fa..d04b78c81e17ef 100644
--- a/libcxx/docs/Status/Cxx26Issues.csv
+++ b/libcxx/docs/Status/Cxx26Issues.csv
@@ -176,7 +176,7 @@
 "`LWG4291 <https://wg21.link/LWG4291>`__","``explicit map(const Allocator&)`` should be ``constexpr``","2025-11 (Kona)","","","`#171333 <https://github.com/llvm/llvm-project/issues/171333>`__",""
 "`LWG4292 <https://wg21.link/LWG4292>`__","Unordered container local iterators should be constexpr iterators","2025-11 (Kona)","","","`#171334 <https://github.com/llvm/llvm-project/issues/171334>`__",""
 "`LWG4293 <https://wg21.link/LWG4293>`__","span::subspan/first/last chooses wrong constructor when T is const-qualified bool","2025-11 (Kona)","","","`#171335 <https://github.com/llvm/llvm-project/issues/171335>`__",""
-"`LWG4294 <https://wg21.link/LWG4294>`__","``bitset(const CharT*)`` constructor needs to be constrained","2025-11 (Kona)","","","`#171336 <https://github.com/llvm/llvm-project/issues/171336>`__",""
+"`LWG4294 <https://wg21.link/LWG4294>`__","``bitset(const CharT*)`` constructor needs to be constrained","2025-11 (Kona)","|Complete|","24","`#171336 <https://github.com/llvm/llvm-project/issues/171336>`__",""
 "`LWG4297 <https://wg21.link/LWG4297>`__","Missing ``permutable`` constraint for iterator overloads in Parallel Range Algorithms","2025-11 (Kona)","","","`#171338 <https://github.com/llvm/llvm-project/issues/171338>`__",""
 "`LWG4299 <https://wg21.link/LWG4299>`__","Missing *Mandates:* part in ``optional<T&>::transform``","2025-11 (Kona)","","","`#171339 <https://github.com/llvm/llvm-project/issues/171339>`__",""
 "`LWG4300 <https://wg21.link/LWG4300>`__","Missing *Returns:* element in ``optional<T&>::emplace``","2025-11 (Kona)","|Complete|","22","`#171340 <https://github.com/llvm/llvm-project/issues/171340>`__",""
diff --git a/libcxx/include/__type_traits/is_char_like_type.h b/libcxx/include/__type_traits/is_char_like_type.h
index ca440b52fcd458..0111a728762e79 100644
--- a/libcxx/include/__type_traits/is_char_like_type.h
+++ b/libcxx/include/__type_traits/is_char_like_type.h
@@ -11,9 +11,11 @@
 
 #include <__config>
 #include <__type_traits/conjunction.h>
+#include <__type_traits/is_array.h>
 #include <__type_traits/is_standard_layout.h>
 #include <__type_traits/is_trivially_constructible.h>
 #include <__type_traits/is_trivially_copyable.h>
+#include <__type_traits/negation.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -21,9 +23,14 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+// [strings.general]: A char-like type is a non-array trivially copyable standard-layout type T
+// where is_trivially_default_constructible_v<T> is true.
 template <class _CharT>
 using _IsCharLikeType _LIBCPP_NODEBUG =
-    _And<is_standard_layout<_CharT>, is_trivially_default_constructible<_CharT>, is_trivially_copyable<_CharT> >;
+    _And<_Not<is_array<_CharT> >,
+         is_standard_layout<_CharT>,
+         is_trivially_default_constructible<_CharT>,
+         is_trivially_copyable<_CharT> >;
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/test/std/utilities/template.bitset/bitset.cons/char_ptr_ctor_constraints.compile.pass.cpp b/libcxx/test/std/utilities/template.bitset/bitset.cons/char_ptr_ctor_constraints.compile.pass.cpp
new file mode 100644
index 00000000000000..a091e4d98457cd
--- /dev/null
+++ b/libcxx/test/std/utilities/template.bitset/bitset.cons/char_ptr_ctor_constraints.compile.pass.cpp
@@ -0,0 +1,80 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <bitset>
+
+// template <class charT>
+//     explicit bitset(const charT* str,
+//                     typename basic_string_view<charT>::size_type n = basic_string_view<charT>::npos,
+//                     charT zero = charT('0'), charT one = charT('1'));
+//
+// Constraints (LWG4294):
+//   - is_array_v<charT> is false,
+//   - is_trivially_copyable_v<charT> is true,
+//   - is_standard_layout_v<charT> is true, and
+//   - is_trivially_default_constructible_v<charT> is true.
+//
+// When the constraints are not met, the constructor must not participate in overload resolution, and checking
+// is_constructible must not cause a hard error.
+
+// The frozen C++03 headers don't implement LWG4294.
+// XFAIL: FROZEN-CXX03-HEADERS-FIXME
+
+#include <bitset>
+#include <type_traits>
+
+#include "test_macros.h"
+
+struct NonTrivialDestructor {
+  ~NonTrivialDestructor() {}
+};
+
+struct NonTrivialDefaultCtor {
+  NonTrivialDefaultCtor() {}
+};
+
+struct NonTriviallyCopyable {
+  NonTriviallyCopyable& operator=(const NonTriviallyCopyable&) { return *this; }
+};
+
+struct NonStandardLayout {
+  int a;
+
+protected:
+  int b;
+};
+
+template <std::size_t N>
+void test() {
+  // Character types satisfying the constraints.
+  static_assert(std::is_constructible<std::bitset<N>, const char*>::value, "");
+  static_assert(std::is_constructible<std::bitset<N>, char*>::value, "");
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  static_assert(std::is_constructible<std::bitset<N>, const wchar_t*>::value, "");
+#endif
+
+  // Array types (the case added by LWG4294).
+  static_assert(!std::is_constructible<std::bitset<N>, const char (*)[2]>::value, "");
+  static_assert(!std::is_constructible<std::bitset<N>, char (*)[2]>::value, "");
+  static_assert(!std::is_constructible<std::bitset<N>, const int (*)[3]>::value, "");
+  static_assert(!std::is_constructible<std::bitset<N>, const char (*)[2][2]>::value, "");
+
+  // Types that are not trivially copyable, standard-layout, or trivially default constructible.
+  static_assert(!std::is_constructible<std::bitset<N>, NonTrivialDestructor*>::value, "");
+  static_assert(!std::is_constructible<std::bitset<N>, const NonTrivialDefaultCtor*>::value, "");
+  static_assert(!std::is_constructible<std::bitset<N>, const NonTriviallyCopyable*>::value, "");
+  static_assert(!std::is_constructible<std::bitset<N>, const NonStandardLayout*>::value, "");
+}
+
+void test_all() {
+  test<0>();
+  test<1>();
+  test<32>();
+  test<64>();
+  test<65>();
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/238119


More information about the libcxx-commits mailing list