Skip to content

[libc++][format] Disables narrow string to wide string formatters. #128355

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 26, 2025

Conversation

mordante
Copy link
Member

@mordante mordante commented Feb 22, 2025

Implements LWG3944: Formatters converting sequences of char to sequences of wchar_t

Fixes: #105342

Implements:
- 3944. Formatters converting sequences of char to sequences of wchar_t

Fixes: llvm#105342
@mordante mordante requested a review from a team as a code owner February 22, 2025 13:40
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Feb 22, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 22, 2025

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

Changes

Implements:

    1. Formatters converting sequences of char to sequences of wchar_t

Fixes: #105342


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

4 Files Affected:

  • (modified) libcxx/docs/Status/Cxx2cIssues.csv (+1-1)
  • (modified) libcxx/include/__format/formatter.h (+7-5)
  • (modified) libcxx/include/__format/formatter_string.h (+13)
  • (modified) libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp (+16)
diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index 1ec23dfabd5ea..8a521e7d6686e 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -62,7 +62,7 @@
 "`LWG4053 <https://wg21.link/LWG4053>`__","Unary call to ``std::views::repeat`` does not decay the argument","2024-03 (Tokyo)","|Complete|","19",""
 "`LWG4054 <https://wg21.link/LWG4054>`__","Repeating a ``repeat_view`` should repeat the view","2024-03 (Tokyo)","|Complete|","19",""
 "","","","","",""
-"`LWG3944 <https://wg21.link/LWG3944>`__","Formatters converting sequences of ``char`` to sequences of ``wchar_t``","2024-06 (St. Louis)","","",""
+"`LWG3944 <https://wg21.link/LWG3944>`__","Formatters converting sequences of ``char`` to sequences of ``wchar_t``","2024-06 (St. Louis)","|Complete|","21",""
 "`LWG4060 <https://wg21.link/LWG4060>`__","``submdspan`` preconditions do not forbid creating invalid pointer","2024-06 (St. Louis)","","",""
 "`LWG4061 <https://wg21.link/LWG4061>`__","Should ``std::basic_format_context`` be default-constructible/copyable/movable?","2024-06 (St. Louis)","|Complete|","19",""
 "`LWG4071 <https://wg21.link/LWG4071>`__","``reference_wrapper`` comparisons are not SFINAE-friendly","2024-06 (St. Louis)","|Complete|","19",""
diff --git a/libcxx/include/__format/formatter.h b/libcxx/include/__format/formatter.h
index 10c244b6d1895..e8386f5ca9c79 100644
--- a/libcxx/include/__format/formatter.h
+++ b/libcxx/include/__format/formatter.h
@@ -21,6 +21,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 20
 
+struct __disabled_formatter {
+  __disabled_formatter()                                       = delete;
+  __disabled_formatter(const __disabled_formatter&)            = delete;
+  __disabled_formatter& operator=(const __disabled_formatter&) = delete;
+};
+
 /// The default formatter template.
 ///
 /// [format.formatter.spec]/5
@@ -31,11 +37,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 /// - is_copy_assignable_v<F>, and
 /// - is_move_assignable_v<F>.
 template <class _Tp, class _CharT>
-struct _LIBCPP_TEMPLATE_VIS formatter {
-  formatter()                            = delete;
-  formatter(const formatter&)            = delete;
-  formatter& operator=(const formatter&) = delete;
-};
+struct _LIBCPP_TEMPLATE_VIS formatter : __disabled_formatter {};
 
 #  if _LIBCPP_STD_VER >= 23
 
diff --git a/libcxx/include/__format/formatter_string.h b/libcxx/include/__format/formatter_string.h
index 30084e582214d..112c731e67ed7 100644
--- a/libcxx/include/__format/formatter_string.h
+++ b/libcxx/include/__format/formatter_string.h
@@ -125,6 +125,19 @@ struct _LIBCPP_TEMPLATE_VIS formatter<basic_string_view<_CharT, _Traits>, _CharT
   }
 };
 
+#  if _LIBCPP_HAS_WIDE_CHARACTERS
+template <>
+struct formatter<char*, wchar_t> : __disabled_formatter {};
+template <>
+struct formatter<const char*, wchar_t> : __disabled_formatter {};
+template <size_t _Size>
+struct formatter<char[_Size], wchar_t> : __disabled_formatter {};
+template <class _Traits, class _Allocator>
+struct formatter<basic_string<char, _Traits, _Allocator>, wchar_t> : __disabled_formatter {};
+template <class _Traits>
+struct formatter<basic_string_view<char, _Traits>, wchar_t> : __disabled_formatter {};
+#  endif // _LIBCPP_HAS_WIDE_CHARACTERS
+
 #  if _LIBCPP_STD_VER >= 23
 template <>
 inline constexpr bool enable_nonlocking_formatter_optimization<char*> = true;
diff --git a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
index ec27acd75e110..ac60307766d24 100644
--- a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp
@@ -292,6 +292,21 @@ void test_LWG3631() {
   assert_is_not_formattable<std::pair<volatile int, volatile int>, CharT>();
 }
 
+void test_LWG3944() {
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+  assert_is_not_formattable<char*, wchar_t>();
+  assert_is_not_formattable<const char*, wchar_t>();
+  assert_is_not_formattable<char[42], wchar_t>();
+  assert_is_not_formattable<std::string, wchar_t>();
+  assert_is_not_formattable<std::string_view, wchar_t>();
+
+  assert_is_formattable<std::vector<char>, wchar_t>();
+  assert_is_formattable<std::set<char>, wchar_t>();
+  assert_is_formattable<std::map<char, char>, wchar_t>();
+  assert_is_formattable<std::tuple<char>, wchar_t>();
+#endif
+}
+
 class c {
   void f();
   void fc() const;
@@ -417,6 +432,7 @@ void test() {
   test_P1636<CharT>();
   test_P2286<CharT>();
   test_LWG3631<CharT>();
+  test_LWG3944();
   test_abstract_class<CharT>();
   test_disabled<CharT>();
 }

@mordante mordante merged commit 26be07b into llvm:main Feb 26, 2025
85 of 89 checks passed
@mordante mordante deleted the review/LWG3944 branch February 26, 2025 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

LWG3944: Formatters converting sequences of char to sequences of wchar_t
3 participants