xref: /llvm-project/libcxx/test/std/utilities/format/format.functions/escaped_output.unicode.pass.cpp (revision 84cdfbcd5558ebbdec091c7ff68de286bb6ef760)
1 //===----------------------------------------------------------------------===//
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 
8 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
9 // UNSUPPORTED: libcpp-has-no-incomplete-format
10 
11 // This version runs the test when the platform has Unicode support.
12 // UNSUPPORTED: libcpp-has-no-unicode
13 
14 // TODO FMT Investigate Windows and AIX issues.
15 // UNSUPPORTED: msvc, target={{.+}}-windows-gnu
16 // UNSUPPORTED: LIBCXX-AIX-FIXME
17 
18 // <format>
19 
20 // This test the debug string type for the formatter specializations for char
21 // and string types. This tests Unicode strings.
22 
23 #include <format>
24 
25 #include <cassert>
26 #include <concepts>
27 #include <list>
28 #include <vector>
29 
30 #include "test_macros.h"
31 #include "make_string.h"
32 #include "test_format_string.h"
33 
34 #ifndef TEST_HAS_NO_LOCALIZATION
35 #  include <iostream>
36 #endif
37 
38 #define SV(S) MAKE_STRING_VIEW(CharT, S)
39 
40 auto test_format = []<class CharT, class... Args>(
41                        std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
42   {
43     std::basic_string<CharT> out = std::format(fmt, std::forward<Args>(args)...);
44 #ifndef TEST_HAS_NO_LOCALIZATION
45     if (out != expected) {
46       if constexpr (std::same_as<CharT, char>)
47         std::cerr << "\nFormat string   " << fmt.get() << "\nExpected output " << expected << "\nActual output   "
48                   << out << '\n';
49 #  ifndef TEST_HAS_NO_WIDE_CHARACTERS
50       else
51         std::wcerr << L"\nFormat string   " << fmt.get() << L"\nExpected output " << expected << L"\nActual output   "
52                    << out << L'\n';
53 #  endif // TEST_HAS_NO_WIDE_CHARACTERS
54     }
55 #endif // TEST_HAS_NO_LOCALIZATION
56     assert(out == expected);
57   }
58 #ifndef TEST_HAS_NO_LOCALIZATION
59   {
60     std::basic_string<CharT> out = std::format(std::locale(), fmt, std::forward<Args>(args)...);
61     assert(out == expected);
62   }
63 #endif // TEST_HAS_NO_LOCALIZATION
64 };
65 
66 auto test_format_to =
67     []<class CharT, class... Args>(
68         std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
69       {
70         std::basic_string<CharT> out(expected.size(), CharT(' '));
71         auto it = std::format_to(out.begin(), fmt, std::forward<Args>(args)...);
72         assert(it == out.end());
73         assert(out == expected);
74       }
75 #ifndef TEST_HAS_NO_LOCALIZATION
76       {
77         std::basic_string<CharT> out(expected.size(), CharT(' '));
78         auto it = std::format_to(out.begin(), std::locale(), fmt, std::forward<Args>(args)...);
79         assert(it == out.end());
80         assert(out == expected);
81       }
82 #endif // TEST_HAS_NO_LOCALIZATION
83       {
84         std::list<CharT> out;
85         std::format_to(std::back_inserter(out), fmt, std::forward<Args>(args)...);
86         assert(std::equal(out.begin(), out.end(), expected.begin(), expected.end()));
87       }
88       {
89         std::vector<CharT> out;
90         std::format_to(std::back_inserter(out), fmt, std::forward<Args>(args)...);
91         assert(std::equal(out.begin(), out.end(), expected.begin(), expected.end()));
92       }
93       {
94         assert(expected.size() < 4096 && "Update the size of the buffer.");
95         CharT out[4096];
96         CharT* it = std::format_to(out, fmt, std::forward<Args>(args)...);
97         assert(std::distance(out, it) == int(expected.size()));
98         // Convert to std::string since output contains '\0' for boolean tests.
99         assert(std::basic_string<CharT>(out, it) == expected);
100       }
101     };
102 
103 auto test_formatted_size =
104     []<class CharT, class... Args>(
105         std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
106       {
107         size_t size = std::formatted_size(fmt, std::forward<Args>(args)...);
108         assert(size == expected.size());
109       }
110 #ifndef TEST_HAS_NO_LOCALIZATION
111       {
112         size_t size = std::formatted_size(std::locale(), fmt, std::forward<Args>(args)...);
113         assert(size == expected.size());
114       }
115 #endif // TEST_HAS_NO_LOCALIZATION
116     };
117 
118 auto test_format_to_n =
119     []<class CharT, class... Args>(
120         std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
121       {
122         size_t n = expected.size();
123         std::basic_string<CharT> out(n, CharT(' '));
124         std::format_to_n_result result = std::format_to_n(out.begin(), n, fmt, std::forward<Args>(args)...);
125         assert(result.size == static_cast<ptrdiff_t>(expected.size()));
126         assert(result.out == out.end());
127         assert(out == expected);
128       }
129 #ifndef TEST_HAS_NO_LOCALIZATION
130       {
131         size_t n = expected.size();
132         std::basic_string<CharT> out(n, CharT(' '));
133         std::format_to_n_result result =
134             std::format_to_n(out.begin(), n, std::locale(), fmt, std::forward<Args>(args)...);
135         assert(result.size == static_cast<ptrdiff_t>(expected.size()));
136         assert(result.out == out.end());
137         assert(out == expected);
138       }
139 #endif // TEST_HAS_NO_LOCALIZATION
140       {
141         ptrdiff_t n = 0;
142         std::basic_string<CharT> out;
143         std::format_to_n_result result = std::format_to_n(out.begin(), n, fmt, std::forward<Args>(args)...);
144         assert(result.size == static_cast<ptrdiff_t>(expected.size()));
145         assert(result.out == out.end());
146         assert(out.empty());
147       }
148       {
149         ptrdiff_t n = expected.size() / 2;
150         std::basic_string<CharT> out(n, CharT(' '));
151         std::format_to_n_result result = std::format_to_n(out.begin(), n, fmt, std::forward<Args>(args)...);
152         assert(result.size == static_cast<ptrdiff_t>(expected.size()));
153         assert(result.out == out.end());
154         assert(out == expected.substr(0, n));
155       }
156     };
157 
158 template <class CharT>
159 void test_char() {
160   // *** P2286 examples ***
161   test_format(SV("['\\'', '\"']"), SV("[{:?}, {:?}]"), CharT('\''), CharT('"'));
162 
163   // *** Specical cases ***
164   test_format(SV("'\\t'"), SV("{:?}"), CharT('\t'));
165   test_format(SV("'\\n'"), SV("{:?}"), CharT('\n'));
166   test_format(SV("'\\r'"), SV("{:?}"), CharT('\r'));
167   test_format(SV("'\\\\'"), SV("{:?}"), CharT('\\'));
168 
169   test_format(SV("'\\\''"), SV("{:?}"), CharT('\''));
170   test_format(SV("'\"'"), SV("{:?}"), CharT('"')); // only special for string
171 
172   test_format(SV("' '"), SV("{:?}"), CharT(' '));
173 
174   // *** Printable ***
175   test_format(SV("'a'"), SV("{:?}"), CharT('a'));
176   test_format(SV("'b'"), SV("{:?}"), CharT('b'));
177   test_format(SV("'c'"), SV("{:?}"), CharT('c'));
178 
179   // *** Non-printable ***
180 
181   // Control
182   test_format(SV("'\\u{0}'"), SV("{:?}"), CharT('\0'));
183   test_format(SV("'\\u{1f}'"), SV("{:?}"), CharT('\x1f'));
184 
185   // Ill-formed
186   if constexpr (sizeof(CharT) == 1)
187     test_format(SV("'\\x{80}'"), SV("{:?}"), CharT('\x80'));
188 
189 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
190   if constexpr (sizeof(CharT) > 1) {
191     using V = std::basic_string_view<CharT>;
192 
193     // Unicode fitting in a 16-bit wchar_t
194 
195     // *** Non-printable ***
196 
197     // Space_Separator
198     test_format(V{L"'\\u{a0}'"}, L"{:?}", L'\xa0');     // NO-BREAK SPACE
199     test_format(V{L"'\\u{3000}'"}, L"{:?}", L'\x3000'); // IDEOGRAPHIC SPACE
200 
201     // Line_Separator
202     test_format(V{L"'\\u{2028}'"}, L"{:?}", L'\x2028'); // LINE SEPARATOR
203 
204     // Paragraph_Separator
205     test_format(V{L"'\\u{2029}'"}, L"{:?}", L'\x2029'); // PARAGRAPH SEPARATOR
206 
207     // Format
208     test_format(V{L"'\\u{ad}'"}, L"{:?}", L'\xad');     // SOFT HYPHEN
209     test_format(V{L"'\\u{600}'"}, L"{:?}", L'\x600');   // ARABIC NUMBER SIGN
210     test_format(V{L"'\\u{feff}'"}, L"{:?}", L'\xfeff'); // ZERO WIDTH NO-BREAK SPACE
211 
212     if constexpr (sizeof(CharT) == 2) {
213       // Incomplete surrogate pair in UTF-16
214       test_format(V{L"'\\x{d800}'"}, L"{:?}", L'\xd800'); // <surrogate-D800>
215       test_format(V{L"'\\x{dfff}'"}, L"{:?}", L'\xdfff'); // <surrogate-DFFF>
216     } else {
217       test_format(V{L"'\\u{d800}'"}, L"{:?}", L'\xd800'); // <surrogate-D800>
218       test_format(V{L"'\\u{dfff}'"}, L"{:?}", L'\xdfff'); // <surrogate-DFFF>
219     }
220 
221     // Private_Use
222     test_format(V{L"'\\u{e000}'"}, L"{:?}", L'\xe000'); // <private-use-E000>
223     test_format(V{L"'\\u{f8ff}'"}, L"{:?}", L'\xf8ff'); // <private-use-F8FF>
224 
225     // Unassigned
226     test_format(V{L"'\\u{378}'"}, L"{:?}", L'\x378');   // <reserved-0378>
227     test_format(V{L"'\\u{1774}'"}, L"{:?}", L'\x1774'); // <reserved-1774>
228     test_format(V{L"'\\u{ffff}'"}, L"{:?}", L'\xffff'); // <noncharacter-FFFF>
229 
230     // Grapheme Extended
231     test_format(V{L"'\\u{300}'"}, L"{:?}", L'\x300');   // COMBINING GRAVE ACCENT
232     test_format(V{L"'\\u{fe20}'"}, L"{:?}", L'\xfe20'); // VARIATION SELECTOR-1
233   }
234 #  ifndef TEST_SHORT_WCHAR
235   if constexpr (sizeof(CharT) > 2) {
236     static_assert(sizeof(CharT) == 4, "add support for unexpected size");
237     // Unicode fitting in a 32-bit wchar_t
238 
239     constexpr wchar_t x  = 0x1ffff;
240     constexpr uint32_t y = 0x1ffff;
241     static_assert(x == y);
242 
243     using V = std::basic_string_view<CharT>;
244 
245     // *** Non-printable ***
246     // Format
247     test_format(V{L"'\\u{110bd}'"}, L"{:?}", L'\x110bd'); // KAITHI NUMBER SIGN
248     test_format(V{L"'\\u{e007f}'"}, L"{:?}", L'\xe007f'); // CANCEL TAG
249 
250     // Private_Use
251     test_format(V{L"'\\u{f0000}'"}, L"{:?}", L'\xf0000'); // <private-use-F0000>
252     test_format(V{L"'\\u{ffffd}'"}, L"{:?}", L'\xffffd'); // <private-use-FFFFD>
253 
254     test_format(V{L"'\\u{100000}'"}, L"{:?}", L'\x100000'); // <private-use-100000>
255     test_format(V{L"'\\u{10fffd}'"}, L"{:?}", L'\x10fffd'); // <private-use-10FFFD>
256 
257     // Unassigned
258     test_format(V{L"'\\u{1000c}'"}, L"{:?}", L'\x1000c');   // <reserved-1000c>
259     test_format(V{L"'\\u{fffff}'"}, L"{:?}", L'\xfffff');   // <noncharacter-FFFFF>
260     test_format(V{L"'\\u{10fffe}'"}, L"{:?}", L'\x10fffe'); // <noncharacter-10FFFE>
261 
262     // Grapheme Extended
263     test_format(V{L"'\\u{101fd}'"}, L"{:?}", L'\x101fd'); // COMBINING OLD PERMIC LETTER AN
264     test_format(V{L"'\\u{e0100}'"}, L"{:?}", L'\xe0100'); // VARIATION SELECTOR-17
265 
266     // Ill-formed
267     test_format(V{L"'\\x{110000}'"}, L"{:?}", L'\x110000');
268     test_format(V{L"'\\x{ffffffff}'"}, L"{:?}", L'\xffffffff');
269   }
270 #  endif // TEST_SHORT_WCHAR
271 #endif   // TEST_HAS_NO_WIDE_CHARACTERS
272 }
273 
274 template <class CharT>
275 void test_string() {
276   // *** P2286 examples ***
277   test_format(SV("[h\tllo]"), SV("[{}]"), SV("h\tllo"));
278   test_format(SV(R"(["h\tllo"])"), SV("[{:?}]"), SV("h\tllo"));
279   test_format(SV(R"(["Спасибо, Виктор ♥!"])"), SV("[{:?}]"), SV("Спасибо, Виктор ♥!"));
280 
281   test_format(SV(R"(["\u{0} \n \t \u{2} \u{1b}"])"), SV("[{:?}]"), SV("\0 \n \t \x02 \x1b"));
282 
283   if constexpr (sizeof(CharT) == 1) {
284     // Ill-formend UTF-8
285     test_format(SV(R"(["\x{c3}"])"), SV("[{:?}]"), "\xc3");
286     test_format(SV(R"(["\x{c3}("])"), SV("[{:?}]"), "\xc3\x28");
287   } else {
288     // Valid UTF-16 and UTF-32
289     test_format(SV("[\"\u00c3\"]"), SV("[{:?}]"), L"\xc3"); // LATIN CAPITAL LETTER A WITH TILDE
290     test_format(SV("[\"\u00c3(\"]"), SV("[{:?}]"), L"\xc3\x28");
291   }
292 
293   test_format(SV(R"(["����\u{200d}♂\u{fe0f}"])"), SV("[{:?}]"), SV("����‍♂️"));
294 
295   // *** Specical cases ***
296   test_format(SV(R"("\t\n\r\\'\" ")"), SV("{:?}"), SV("\t\n\r\\'\" "));
297 
298   // *** Printable ***
299   test_format(SV(R"("abcdefg")"), SV("{:?}"), SV("abcdefg"));
300 
301   // *** Non-printable ***
302 
303   // Control
304   test_format(SV(R"("\u{0}\u{1f}")"), SV("{:?}"), SV("\0\x1f"));
305 
306   // Ill-formed
307   if constexpr (sizeof(CharT) == 1)
308     test_format(SV(R"("\x{80}")"), SV("{:?}"), SV("\x80"));
309 
310 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
311   if constexpr (sizeof(CharT) > 1) {
312     using V = std::basic_string_view<CharT>;
313 
314     // Unicode fitting in a 16-bit wchar_t
315 
316     // *** Non-printable ***
317 
318     // Space_Separator
319     test_format(V{LR"("\u{a0}\u{3000}")"}, L"{:?}", L"\xa0\x3000");
320 
321     // Line_Separator
322     test_format(V{LR"("\u{2028}")"}, L"{:?}", L"\x2028"); // LINE SEPARATOR
323 
324     // Paragraph_Separator
325     test_format(V{LR"("\u{2029}")"}, L"{:?}", L"\x2029"); // PARAGRAPH SEPARATOR
326 
327     // Format
328     test_format(V{LR"("\u{ad}\u{600}\u{feff}")"}, L"{:?}", L"\xad\x600\xfeff");
329 
330     if constexpr (sizeof(CharT) == 2)
331       // Incomplete surrogate pair in UTF-16
332       test_format(V{LR"("\x{d800}")"}, L"{:?}", L"\xd800");
333     else
334       test_format(V{LR"("\u{d800}")"}, L"{:?}", L"\xd800");
335 
336     // Private_Use
337     test_format(V{LR"("\u{e000}\u{f8ff}")"}, L"{:?}", L"\xe000\xf8ff");
338 
339     // Unassigned
340     test_format(V{LR"("\u{378}\u{1774}\u{ffff}")"}, L"{:?}", L"\x378\x1774\xffff");
341 
342     // Grapheme Extended
343     test_format(V{LR"("\u{300}\u{fe20}")"}, L"{:?}", L"\x300\xfe20");
344   }
345 #  ifndef TEST_SHORT_WCHAR
346   if constexpr (sizeof(CharT) > 2) {
347     static_assert(sizeof(CharT) == 4, "add support for unexpected size");
348     // Unicode fitting in a 32-bit wchar_t
349 
350     constexpr wchar_t x  = 0x1ffff;
351     constexpr uint32_t y = 0x1ffff;
352     static_assert(x == y);
353 
354     using V = std::basic_string_view<CharT>;
355 
356     // *** Non-printable ***
357     // Format
358     test_format(V{LR"("\u{110bd}\u{e007f}")"}, L"{:?}", L"\x110bd\xe007f");
359 
360     // Private_Use
361     test_format(V{LR"("\u{f0000}\u{ffffd}\u{100000}\u{10fffd}")"}, L"{:?}", L"\xf0000\xffffd\x100000\x10fffd");
362 
363     // Unassigned
364     test_format(V{LR"("\u{1000c}\u{fffff}\u{10fffe}")"}, L"{:?}", L"\x1000c\xfffff\x10fffe");
365 
366     // Grapheme Extended
367     test_format(V{LR"("\u{101fd}\u{e0100}")"}, L"{:?}", L"\x101fd\xe0100");
368 
369     // Ill-formed
370     test_format(V{LR"("\x{110000}\x{ffffffff}")"}, L"{:?}", L"\x110000\xffffffff");
371   }
372 #  endif // TEST_SHORT_WCHAR
373 #endif   // TEST_HAS_NO_WIDE_CHARACTERS
374 }
375 
376 template <class CharT, class TestFunction>
377 void test_format_functions(TestFunction check) {
378   // *** align-fill & width ***
379   check(SV(R"(***"hellö")"), SV("{:*>10?}"), SV("hellö")); // ö is LATIN SMALL LETTER O WITH DIAERESIS
380   check(SV(R"(*"hellö"**)"), SV("{:*^10?}"), SV("hellö"));
381   check(SV(R"("hellö"***)"), SV("{:*<10?}"), SV("hellö"));
382 
383   check(SV(R"("hello\u{308}")"), SV("{:*>10?}"), SV("hello\u0308"));
384   check(SV(R"(***"hello\u{308}")"), SV("{:*>17?}"), SV("hello\u0308"));
385   check(SV(R"(*"hello\u{308}"**)"), SV("{:*^17?}"), SV("hello\u0308"));
386   check(SV(R"("hello\u{308}"***)"), SV("{:*<17?}"), SV("hello\u0308"));
387 
388   check(SV(R"("hello ����\u{200d}♂\u{fe0f}")"), SV("{:*>10?}"), SV("hello ����‍♂️"));
389   check(SV(R"(***"hello ����\u{200d}♂\u{fe0f}")"), SV("{:*>30?}"), SV("hello ����‍♂️"));
390   check(SV(R"(*"hello ����\u{200d}♂\u{fe0f}"**)"), SV("{:*^30?}"), SV("hello ����‍♂️"));
391   check(SV(R"("hello ����\u{200d}♂\u{fe0f}"***)"), SV("{:*<30?}"), SV("hello ����‍♂️"));
392 
393   // *** width ***
394   check(SV(R"("hellö"   )"), SV("{:10?}"), SV("hellö"));
395   check(SV(R"("hello\u{308}"   )"), SV("{:17?}"), SV("hello\u0308"));
396   check(SV(R"("hello ����\u{200d}♂\u{fe0f}"   )"), SV("{:30?}"), SV("hello ����‍♂️"));
397 
398   // *** precision ***
399   check(SV(R"("hell)"), SV("{:.5?}"), SV("hellö"));
400   check(SV(R"("hellö)"), SV("{:.6?}"), SV("hellö"));
401   check(SV(R"("hellö")"), SV("{:.7?}"), SV("hellö"));
402 
403   check(SV(R"("hello )"), SV("{:.7?}"), SV("hello ����‍♂️"));
404   check(SV(R"("hello )"), SV("{:.8?}"), SV("hello ����‍♂️")); // shrug is two columns
405   check(SV(R"("hello ����)"), SV("{:.9?}"), SV("hello ����‍♂️"));
406   check(SV(R"("hello ����\)"), SV("{:.10?}"), SV("hello ����‍♂️"));
407   check(SV(R"("hello ����\u{200d})"), SV("{:.17?}"), SV("hello ����‍♂️"));
408   check(SV(R"("hello ����\u{200d}♂)"), SV("{:.18?}"), SV("hello ����‍♂️"));
409   check(SV(R"("hello ����\u{200d}♂\)"), SV("{:.19?}"), SV("hello ����‍♂️"));
410   check(SV(R"("hello ����\u{200d}♂\u{fe0f}")"), SV("{:.28?}"), SV("hello ����‍♂️"));
411 
412   // *** width & precision ***
413   check(SV(R"("hell#########################)"), SV("{:#<30.5?}"), SV("hellö"));
414   check(SV(R"("hellö########################)"), SV("{:#<30.6?}"), SV("hellö"));
415   check(SV(R"("hellö"#######################)"), SV("{:#<30.7?}"), SV("hellö"));
416 
417   check(SV(R"("hello #######################)"), SV("{:#<30.7?}"), SV("hello ����‍♂️"));
418   check(SV(R"("hello #######################)"), SV("{:#<30.8?}"), SV("hello ����‍♂️"));
419   check(SV(R"("hello ����#####################)"), SV("{:#<30.9?}"), SV("hello ����‍♂️"));
420   check(SV(R"("hello ����\####################)"), SV("{:#<30.10?}"), SV("hello ����‍♂️"));
421   check(SV(R"("hello ����\u{200d}#############)"), SV("{:#<30.17?}"), SV("hello ����‍♂️"));
422   check(SV(R"("hello ����\u{200d}♂############)"), SV("{:#<30.18?}"), SV("hello ����‍♂️"));
423   check(SV(R"("hello ����\u{200d}♂\###########)"), SV("{:#<30.19?}"), SV("hello ����‍♂️"));
424   check(SV(R"("hello ����\u{200d}♂\u{fe0f}"###)"), SV("{:#<30.28?}"), SV("hello ����‍♂️"));
425 }
426 
427 template <class CharT>
428 void test() {
429   test_char<CharT>();
430   test_string<CharT>();
431 
432   test_format_functions<CharT>(test_format);
433   test_format_functions<CharT>(test_format_to);
434   test_format_functions<CharT>(test_formatted_size);
435   test_format_functions<CharT>(test_format_to_n);
436 }
437 
438 static void test_ill_formed_utf8() {
439   using namespace std::literals;
440 
441   // Too few code units
442   test_format(R"("\x{df}")"sv, "{:?}", "\xdf");
443   test_format(R"("\x{ef}")"sv, "{:?}", "\xef");
444   test_format(R"("\x{ef}\x{bf}")"sv, "{:?}", "\xef\xbf");
445   test_format(R"("\x{f7}")"sv, "{:?}", "\xf7");
446   test_format(R"("\x{f7}\x{bf}")"sv, "{:?}", "\xf7\xbf");
447   test_format(R"("\x{f7}\x{bf}\x{bf}")"sv, "{:?}", "\xf7\xbf\xbf");
448 
449   // Invalid continuation byte
450   test_format(R"("\x{df}a")"sv,
451               "{:?}",
452               "\xdf"
453               "a");
454   test_format(R"("\x{ef}a")"sv,
455               "{:?}",
456               "\xef"
457               "a");
458   test_format(R"("\x{ef}\x{bf}a")"sv,
459               "{:?}",
460               "\xef\xbf"
461               "a");
462   test_format(R"("\x{f7}a")"sv,
463               "{:?}",
464               "\xf7"
465               "a");
466   test_format(R"("\x{f7}\x{bf}a")"sv,
467               "{:?}",
468               "\xf7\xbf"
469               "a");
470   test_format(R"("\x{f7}\x{bf}\x{bf}a")"sv,
471               "{:?}",
472               "\xf7\xbf\xbf"
473               "a");
474 
475   // Code unit out of range
476   test_format(R"("\u{10ffff}")"sv, "{:?}", "\xf4\x8f\xbf\xbf");               // last valid code point
477   test_format(R"("\x{f4}\x{90}\x{80}\x{80}")"sv, "{:?}", "\xf4\x90\x80\x80"); // first invalid code point
478   test_format(R"("\x{f5}\x{b1}\x{b2}\x{b3}")"sv, "{:?}", "\xf5\xb1\xb2\xb3");
479   test_format(R"("\x{f7}\x{bf}\x{bf}\x{bf}")"sv, "{:?}", "\xf7\xbf\xbf\xbf"); // largest encoded code point
480 }
481 
482 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
483 #  ifdef _LIBCPP_SHORT_WCHAR
484 static void test_ill_formed_utf16() {
485   using namespace std::literals;
486 
487   // Too few code units
488   test_format(LR"("\x{d800}")"sv, L"{:?}", L"\xd800");
489   test_format(LR"("\x{dbff}")"sv, L"{:?}", L"\xdbff");
490 
491   // Start with low surrogate pair
492   test_format(LR"("\x{dc00}a")"sv,
493               L"{:?}",
494               L"\xdc00"
495               "a");
496   test_format(LR"("\x{dfff}a")"sv,
497               L"{:?}",
498               L"\xdfff"
499               "a");
500 
501   // Only high surrogate pair
502   test_format(LR"("\x{d800}a")"sv,
503               L"{:?}",
504               L"\xd800"
505               "a");
506   test_format(LR"("\x{dbff}a")"sv,
507               L"{:?}",
508               L"\xdbff"
509               "a");
510 }
511 #  else // _LIBCPP_SHORT_WCHAR
512 static void test_ill_formed_utf32() {
513   using namespace std::literals;
514 
515   test_format(LR"("\u{10ffff}")"sv, L"{:?}", L"\x10ffff");     // last valid code point
516   test_format(LR"("\x{110000}")"sv, L"{:?}", L"\x110000");     // first invalid code point
517   test_format(LR"("\x{ffffffff}")"sv, L"{:?}", L"\xffffffff"); // largest encoded code point
518 }
519 
520 #  endif // _LIBCPP_SHORT_WCHAR
521 #endif   // TEST_HAS_NO_WIDE_CHARACTERS
522 
523 int main(int, char**) {
524   test<char>();
525 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
526   test<wchar_t>();
527 #endif
528 
529   test_ill_formed_utf8();
530 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
531 #  ifdef _LIBCPP_SHORT_WCHAR
532   test_ill_formed_utf16();
533   assert(false);
534 #  else  // _LIBCPP_SHORT_WCHAR
535   test_ill_formed_utf32();
536 #  endif // _LIBCPP_SHORT_WCHAR
537 #endif   // TEST_HAS_NO_WIDE_CHARACTERS
538 
539   return 0;
540 }
541