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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cIssues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -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",""
Expand Down
12 changes: 7 additions & 5 deletions libcxx/include/__format/formatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down
13 changes: 13 additions & 0 deletions libcxx/include/__format/formatter_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -417,6 +432,7 @@ void test() {
test_P1636<CharT>();
test_P2286<CharT>();
test_LWG3631<CharT>();
test_LWG3944();
test_abstract_class<CharT>();
test_disabled<CharT>();
}
Expand Down