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