[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 17:59:09 PST 2026
https://github.com/antcybersec updated https://github.com/llvm/llvm-project/pull/238119
>From 443e14084230626dc68b5efca01ee4439eab55ec Mon Sep 17 00:00:00 2001
From: anant <170962632+antcybersec at users.noreply.github.com>
Date: Tue, 3 Nov 2026 02:44:51 +0530
Subject: [PATCH 1/2] [libc++] Implement LWG4294: bitset(const CharT*)
constructor needs to be constrained
LWG4294 constrains bitset's `const charT*` constructor to char-like types:
non-array, trivially copyable, standard-layout and trivially default
constructible. libc++ already constrained the constructor with
`_IsCharLikeType`, but the trait was missing the non-array requirement. As a
result, `is_constructible<bitset<N>, const char (*)[2]>` hit a hard error
inside `basic_string<char[2]>` instead of evaluating to false.
Add the missing `!is_array` check to `_IsCharLikeType`, matching the
definition of a char-like type in [strings.general]. The trait is only used by
this constructor. Like other LWG issues, the fix applies to all language
modes; the frozen C++03 headers are left unchanged.
Fixes #171336
Signed-off-by: anant <170962632+antcybersec at users.noreply.github.com>
---
libcxx/docs/Status/Cxx26Issues.csv | 2 +-
.../include/__type_traits/is_char_like_type.h | 9 ++-
...char_ptr_ctor_constraints.compile.pass.cpp | 80 +++++++++++++++++++
3 files changed, 89 insertions(+), 2 deletions(-)
create mode 100644 libcxx/test/std/utilities/template.bitset/bitset.cons/char_ptr_ctor_constraints.compile.pass.cpp
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>();
+}
>From f9309342a5b9266b08e064a7f95fd0a914caf974 Mon Sep 17 00:00:00 2001
From: anant <170962632+antcybersec at users.noreply.github.com>
Date: Tue, 3 Nov 2026 07:25:58 +0530
Subject: [PATCH 2/2] Address review comments
- Don't mention LWG4294 in the description of the constraints, and drop the
explanation of what the constraints require.
- Clarify the comments for the array and class type cases.
- Include <cstddef> for std::size_t.
- Rename test_all() to test().
Signed-off-by: anant <170962632+antcybersec at users.noreply.github.com>
---
.../char_ptr_ctor_constraints.compile.pass.cpp | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
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
index a091e4d98457cd..aa59435343e62a 100644
--- 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
@@ -13,19 +13,17 @@
// typename basic_string_view<charT>::size_type n = basic_string_view<charT>::npos,
// charT zero = charT('0'), charT one = charT('1'));
//
-// Constraints (LWG4294):
+// Constraints:
// - 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 <cstddef>
#include <type_traits>
#include "test_macros.h"
@@ -58,20 +56,20 @@ void test() {
static_assert(std::is_constructible<std::bitset<N>, const wchar_t*>::value, "");
#endif
- // Array types (the case added by LWG4294).
+ // Array types.
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.
+ // Class 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() {
+void test() {
test<0>();
test<1>();
test<32>();
More information about the libcxx-commits
mailing list