[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:52:58 PST 2026
https://github.com/antcybersec created https://github.com/llvm/llvm-project/pull/238119
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
>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] [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>();
+}
More information about the libcxx-commits
mailing list