1 // { dg-options "-fexec-charset=UTF-8" }
2 // { dg-do run { target c++20 } }
3 // { dg-add-options no_pch }
7 #ifndef __cpp_lib_format
8 # error "Feature test macro for std::format is missing in <format>"
9 #elif __cpp_lib_format < 202110L
10 # error "Feature test macro for std::format has wrong value in <format>"
13 #ifndef __cpp_lib_format_uchar
14 # error "Feature test macro for formatting chars as integers is missing in <format>"
15 #elif __cpp_lib_format_uchar < 202311L
16 # error "Feature test macro for formatting chars as integers has wrong value in <format>"
19 #undef __cpp_lib_format
21 #ifndef __cpp_lib_format
22 # error "Feature test macro for std::format is missing in <version>"
23 #elif __cpp_lib_format < 202110L
24 # error "Feature test macro for std::format has wrong value in <version>"
27 #ifndef __cpp_lib_format_uchar
28 # error "Feature test macro for formatting chars as integers is missing in <version>"
29 #elif __cpp_lib_format_uchar < 202311L
30 # error "Feature test macro for formatting chars as integers has wrong value in <version>"
37 #include <testsuite_hooks.h>
43 s
= std::format("disco");
44 VERIFY( s
== "disco" );
46 s
= std::format("}} machine {{ funk }} specialists {{");
47 VERIFY( s
== "} machine { funk } specialists {" );
49 s
= std::format("128bpm }}");
50 VERIFY( s
== "128bpm }" );
56 #ifdef __cpp_exceptions
57 for (auto f
: { "{", "}", "{{{", "{{}", "}{", "{{{{{" })
59 (void) std::vformat(f
, std::make_format_args());
61 } catch (const std::format_error
& e
) {
62 std::string what
= e
.what();
63 VERIFY( what
.find("unmatched") != what
.npos
);
68 struct brit_punc
: std::numpunct
<char>
70 std::string
do_grouping() const override
{ return "\3\3"; }
71 char do_thousands_sep() const override
{ return ','; }
72 std::string
do_truename() const override
{ return "yes mate"; }
73 std::string
do_falsename() const override
{ return "nah bruv"; }
81 string s
= format("{0}-{{", 8); // value of s is "8-{"
87 string s0
= format("{:6}", 42);
89 string s1
= format("{:6}", 'x');
91 string s2
= format("{:*<6}", 'x');
92 VERIFY(s2
== "x*****");
93 string s3
= format("{:*>6}", 'x');
94 VERIFY(s3
== "*****x");
95 string s4
= format("{:*^6}", 'x');
96 VERIFY(s4
== "**x***");
97 string s5
= format("{:6d}", c
);
99 string s6
= format("{:6}", true);
100 VERIFY(s6
== "true ");
101 string s7
= format("{:*<6.3}", "123456");
102 VERIFY( s7
== "123***" );
103 string s8
= format("{:02}", 1234);
104 VERIFY( s8
== "1234" );
105 string s9
= format("{:*<}", "12");
106 VERIFY( s9
== "12" );
107 string sA
= format("{:*<6}", "12345678");
108 VERIFY( sA
== "12345678" );
109 string sB
= format("{:🤡^6}", "x");
110 VERIFY( sB
== "🤡🤡x🤡🤡🤡" );
111 string sC
= format("{:*^6}", "🤡🤡🤡");
112 VERIFY( sC
== "🤡🤡🤡" );
117 double inf
= numeric_limits
<double>::infinity();
118 double nan
= numeric_limits
<double>::quiet_NaN();
119 string s0
= format("{0:},{0:+},{0:-},{0: }", 1);
120 VERIFY(s0
== "1,+1,1, 1");
121 string s1
= format("{0:},{0:+},{0:-},{0: }", -1);
122 VERIFY(s1
== "-1,-1,-1,-1");
123 string s2
= format("{0:},{0:+},{0:-},{0: }", inf
);
124 VERIFY(s2
== "inf,+inf,inf, inf");
125 string s3
= format("{0:},{0:+},{0:-},{0: }", nan
);
126 VERIFY(s3
== "nan,+nan,nan, nan");
129 // alternate form and zero fill
132 string s1
= format("{:+06d}", c
);
133 VERIFY(s1
== "+00120");
134 string s2
= format("{:#06x}", 0xa);
135 VERIFY(s2
== "0x000a");
136 string s3
= format("{:<06}", -42);
137 VERIFY(s3
== "-42 "); // 0 is ignored because of < alignment
140 // integer presentation types
142 // Change global locale so "{:L}" adds digit separators.
143 std::locale::global(std::locale({}, new brit_punc
));
145 string s0
= format("{}", 42);
147 string s1
= format("{0:b} {0:d} {0:o} {0:x}", 42);
148 VERIFY(s1
== "101010 42 52 2a");
149 string s2
= format("{0:#x} {0:#X}", 42);
150 VERIFY(s2
== "0x2a 0X2A");
151 string s3
= format("{:L}", 1234);
152 VERIFY(s3
== "1,234");
154 // Test locale's "byte-and-a-half" grouping (Imperial word? tribble?).
155 string s4
= format("{:#Lx}", 0xfffff);
156 VERIFY(s4
== "0xff,fff");
159 std::locale::global(std::locale::classic());
161 string s5
= format("{}", -100); // PR libstdc++/114325
162 VERIFY(s5
== "-100");
163 string s6
= format("{:d} {:d}", -123, 999);
164 VERIFY(s6
== "-123 999");
169 test_alternate_forms()
173 s
= std::format("{0:#b} {0:+#B} {0:#o} {0:#x} {0:+#X} {0: #d}", 42);
174 VERIFY( s
== "0b101010 +0B101010 052 0x2a +0X2A 42" );
175 s
= std::format("{0:#b} {0:+#B} {0:#o} {0:#x} {0:+#X} {0: #d}", 0);
176 VERIFY( s
== "0b0 +0B0 0 0x0 +0X0 0" );
178 s
= std::format("{0:+#012g} {0:+#014g} {0:+#014g}", 1234.0);
179 VERIFY( s
== "+00001234.00 +0000001234.00 +0000001234.00" );
180 s
= std::format("{0:+#0{1}g} {0:+#0{2}g} {0:+#0{2}g}", 1234.5, 12, 14);
181 VERIFY( s
== "+00001234.50 +0000001234.50 +0000001234.50" );
183 s
= std::format("{:#.2g}", -0.0);
184 VERIFY( s
== "-0.0" );
186 // PR libstdc++/108046
187 s
= std::format("{0:#.0} {0:#.1} {0:#.0g}", 10.0);
188 VERIFY( s
== "1.e+01 1.e+01 1.e+01" );
190 // PR libstdc++/113512
191 s
= std::format("{:#.3g}", 0.025);
192 VERIFY( s
== "0.0250" );
193 s
= std::format("{:#07.3g}", 0.02);
194 VERIFY( s
== "00.0200" );
200 double inf
= std::numeric_limits
<double>::infinity();
201 double nan
= std::numeric_limits
<double>::quiet_NaN();
203 s
= std::format("{0} {0:e} {0:E} {0:f} {0:F} {0:g} {0:G} {0:a} {0:A}", inf
);
204 VERIFY( s
== "inf inf INF inf INF inf INF inf INF" );
205 s
= std::format("{0} {0:e} {0:E} {0:f} {0:F} {0:g} {0:G} {0:a} {0:A}", nan
);
206 VERIFY( s
== "nan nan NAN nan NAN nan NAN nan NAN" );
209 struct euro_punc
: std::numpunct
<char>
211 std::string
do_grouping() const override
{ return "\3\3"; }
212 char do_thousands_sep() const override
{ return '.'; }
213 char do_decimal_point() const override
{ return ','; }
219 // The default C locale.
220 std::locale cloc
= std::locale::classic();
221 // A custom locale using comma digit separators.
222 std::locale
bloc(cloc
, new brit_punc
);
223 // A custom locale using period digit separators.
224 std::locale
eloc(cloc
, new euro_punc
);
228 // Change the global locale:
229 std::locale::global(bloc
);
230 // Format using the global locale:
231 s
= std::format("{0:L} {0:Lx} {0:Lb}", 12345);
232 VERIFY( s
== "12,345 3,039 11,000,000,111,001" );
233 s
= std::format("{0:L} {0:.7Lg} {0:La}", 12345.6789);
234 VERIFY( s
== "12,345.6789 12,345.68 1.81cd6e631f8a1p+13" );
236 s
= std::format("{0:s} {0:L} {1:Ls} {0:Ld}", true, false);
237 VERIFY( s
== "true yes mate nah bruv 1" );
239 // Format using a specific locale:
240 s
= std::format(eloc
, "{0:L} {0:Lx} {0:Lb}", 12345);
241 VERIFY( s
== "12.345 3.039 11.000.000.111.001" );
242 s
= std::format(eloc
, "{0:L} {0:.7LG} {0:La}", 12345.6789);
243 VERIFY( s
== "12.345,6789 12.345,68 1,81cd6e631f8a1p+13" );
245 s
= std::format(eloc
, "{0:#Lg} {0:+#.3Lg} {0:#08.4Lg}", -1234.);
246 VERIFY( s
== "-1.234,00 -1,23e+03 -01.234," );
248 s
= std::format(cloc
, "{:05L}", -1.0); // PR libstdc++/110968
249 VERIFY( s
== "-0001" );
251 // PR libstdc++/114863 grouping applied to nan and inf
252 double inf
= std::numeric_limits
<double>::infinity();
253 s
= std::format(eloc
, "{0:Le} {0:Lf} {0:Lg}", -inf
);
254 VERIFY( s
== "-inf -inf -inf" );
255 double nan
= std::numeric_limits
<double>::quiet_NaN();
256 s
= std::format(eloc
, "{0:Le} {0:Lf} {0:Lg}", -nan
);
257 VERIFY( s
== "-nan -nan -nan" );
260 std::locale::global(cloc
);
268 s
= std::format("{:4}", "");
270 s
= std::format("{:{}}", "", 3);
272 s
= std::format("{:{}}|{:{}}", 1, 2, 3, 4);
273 VERIFY( s
== " 1| 3" );
274 s
= std::format("{1:{0}}", 2, "");
276 s
= std::format("{:03}", 9);
277 VERIFY( s
== "009" );
279 s
= std::format("DR {0:{1}}: allow width {1} from arg-id", 3721, 0);
280 VERIFY( s
== "DR 3721: allow width 0 from arg-id" );
283 s
= std::format("Negative width is an error: {0:{1}}", 123, -1);
285 } catch (const std::format_error
&) {
289 bool no
= false, yes
= true;
290 auto args
= std::make_format_args(no
, yes
);
291 s
= std::vformat("DR 3720: restrict type of width arg-id {0:{1}}", args
);
293 } catch (const std::format_error
&) {
297 char wat
= '?', bang
= '!';
298 auto args
= std::make_format_args(wat
, bang
);
299 s
= std::vformat("DR 3720: restrict type of width arg-id {0:{1}}", args
);
301 } catch (const std::format_error
&) {
310 s
= std::format("{}", 'a');
313 s
= std::format("{:c} {:d} {:o}", 'b', '\x17', '\x3f');
314 VERIFY( s
== "b 23 77" );
316 s
= std::format("{:#d} {:#o}", '\x17', '\x3f');
317 VERIFY( s
== "23 077" );
319 s
= std::format("{:04d} {:04o}", '\x17', '\x3f');
320 VERIFY( s
== "0023 0077" );
322 s
= std::format("{:b} {:B} {:#b} {:#B}", '\xff', '\xa0', '\x17', '\x3f');
323 VERIFY( s
== "11111111 10100000 0b10111 0B111111" );
325 s
= std::format("{:x} {:#x} {:#X}", '\x12', '\x34', '\x45');
326 VERIFY( s
== "12 0x34 0X45" );
328 // P2909R4 Fix formatting of code units as integers (Dude, where’s my char?)
329 // char and wchar_t should be converted to unsigned when formatting them
330 // with an integer presentation type.
331 s
= std::format("{0:b} {0:B} {0:d} {0:o} {0:x} {0:X}", '\xf0');
332 VERIFY( s
== "11110000 11110000 240 360 f0 F0" );
338 using namespace std::literals
;
341 s
= std::format(L
"{}", L
'a');
344 s
= std::format(L
"{} {} {} {} {} {}", L
'0', 1, 2LL, 3.4, L
"five", L
"six"s
);
345 VERIFY( s
== L
"0 1 2 3.4 five six" );
348 s
= std::format(loc
, L
"{:L} {:.3s}{:Lc}", true, L
"data"sv
, '.');
349 VERIFY( s
== L
"true dat." );
351 s
= std::format(L
"{}", 0.0625);
352 VERIFY( s
== L
"0.0625" );
353 s
= std::format(L
"{}", 0.25);
354 VERIFY( s
== L
"0.25" );
355 s
= std::format(L
"{:+a} {:A}", 0x1.23p45
, -0x1.abcdefp
-15);
356 VERIFY( s
== L
"+1.23p+45 -1.ABCDEFP-15" );
358 double inf
= std::numeric_limits
<double>::infinity();
359 double nan
= std::numeric_limits
<double>::quiet_NaN();
360 s
= std::format(L
"{0} {0:F} {1} {1:E}", -inf
, -nan
);
361 VERIFY( s
== L
"-inf -INF -nan -NAN" );
363 s
= std::format(L
"{0:#b} {0:#B} {0:#x} {0:#X}", 99);
364 VERIFY( s
== L
"0b1100011 0B1100011 0x63 0X63" );
366 // P2909R4 Fix formatting of code units as integers (Dude, where’s my char?)
367 s
= std::format(L
"{:d} {:d}", wchar_t(-1), char(-1));
368 VERIFY( s
.find('-') == std::wstring::npos
);
374 auto check
= []<typename T
, typename U
= std::make_unsigned_t
<T
>>(T
, U
= 0) {
375 const int digits
= std::numeric_limits
<T
>::digits
;
376 const std::string
zeros(digits
, '0');
377 const std::string
ones(digits
, '1');
378 auto s
= std::format("{:b}" , std::numeric_limits
<T
>::min());
379 VERIFY( s
== "-1" + zeros
);
380 s
= std::format("{:b}" , std::numeric_limits
<T
>::max());
382 s
= std::format("{:0{}b}" , std::numeric_limits
<U
>::min(), digits
+ 1);
383 VERIFY( s
== '0' + zeros
);
384 s
= std::format("{:b}" , std::numeric_limits
<U
>::max());
385 VERIFY( s
== '1' + ones
);
387 check((signed char)(0)); // int8_t is char on Solaris, see PR 113450
388 check(std::int16_t(0));
389 check(std::int32_t(0));
390 check(std::int64_t(0));
391 #ifdef __SIZEOF_INT128__
392 // std::make_unsigned_t<__int128> is invalid for strict -std=c++20 mode,
393 // so pass a second argument of the unsigned type.
394 check(__int128(0), (unsigned __int128
)(0));
399 test_p1652r1() // printf corner cases in std::format
403 // Problem 1: "#o" specification should not print 0 as "00"
404 s
= std::format("{:#o}", 0);
407 // Problem 2: 'c' should be able to print 65 as "A" (ASCII)
409 s
= std::format("{:c}", c
);
412 // Problem 3: "-000nan" is not a floating point value
413 double nan
= std::numeric_limits
<double>::quiet_NaN();
415 s
= std::vformat("{:0=6}", std::make_format_args(nan
));
417 } catch (const std::format_error
&) {
420 s
= std::format("{:06}", nan
);
421 VERIFY( s
== " nan" );
423 // Problem 4: bool needs a type format specifier
424 s
= std::format("{:s}", true);
425 VERIFY( s
== "true" );
427 // Problem 5: double does not roundtrip float
428 s
= std::format("{}", 3.31f
);
429 VERIFY( s
== "3.31" );
437 std::string s
, str_int
;
439 s
= std::format("{}", p
);
440 VERIFY( s
== "0x0" );
442 s
= std::format("{} {} {}", p
, pc
, nullptr);
443 VERIFY( s
== "0x0 0x0 0x0" );
444 s
= std::format("{:p} {:p} {:p}", p
, pc
, nullptr);
445 VERIFY( s
== "0x0 0x0 0x0" );
446 s
= std::format("{:4},{:5},{:6}", p
, pc
, nullptr); // width
447 VERIFY( s
== " 0x0, 0x0, 0x0" );
448 s
= std::format("{:<4},{:>5},{:^7}", p
, pc
, nullptr); // align+width
449 VERIFY( s
== "0x0 , 0x0, 0x0 " );
450 s
= std::format("{:o<4},{:o>5},{:o^7}", p
, pc
, nullptr); // fill+align+width
451 VERIFY( s
== "0x0o,oo0x0,oo0x0oo" );
454 str_int
= std::format("{:#x}", reinterpret_cast<std::uintptr_t>(p
));
455 s
= std::format("{} {} {}", p
, pc
, nullptr);
456 VERIFY( s
== (str_int
+ ' ' + str_int
+ " 0x0") );
457 str_int
= std::format("{:#20x}", reinterpret_cast<std::uintptr_t>(p
));
458 s
= std::format("{:20} {:20p}", p
, pc
);
459 VERIFY( s
== (str_int
+ ' ' + str_int
) );
461 #if __cplusplus > 202302L || ! defined __STRICT_ANSI__
462 // P2510R3 Formatting pointers
463 s
= std::format("{:06} {:07P} {:08p}", (void*)0, (const void*)0, nullptr);
464 VERIFY( s
== "0x0000 0X00000 0x000000" );
465 str_int
= std::format("{:#016x}", reinterpret_cast<std::uintptr_t>(p
));
466 s
= std::format("{:016} {:016}", p
, pc
);
467 VERIFY( s
== (str_int
+ ' ' + str_int
) );
468 str_int
= std::format("{:#016X}", reinterpret_cast<std::uintptr_t>(p
));
469 s
= std::format("{:016P} {:016P}", p
, pc
);
470 VERIFY( s
== (str_int
+ ' ' + str_int
) );
479 s
= std::format("{}", true);
480 VERIFY( s
== "true" );
481 s
= std::format("{:} {:s}", true, false);
482 VERIFY( s
== "true false" );
483 s
= std::format("{:b} {:#b}", true, false);
484 VERIFY( s
== "1 0b0" );
485 s
= std::format("{:B} {:#B}", false, true);
486 VERIFY( s
== "0 0B1" );
487 s
= std::format("{:d} {:#d}", false, true);
488 VERIFY( s
== "0 1" );
489 s
= std::format("{:o} {:#o} {:#o}", false, true, false);
490 VERIFY( s
== "0 01 0" );
491 s
= std::format("{:x} {:#x} {:#X}", false, true, false);
492 VERIFY( s
== "0 0x1 0X0" );
498 // Similar to sC example in test_std_examples, but not from the standard.
499 // Verify that the character "🤡" has estimated field width 2,
500 // rather than estimated field width equal to strlen("🤡"), which would be 4.
501 std::string sC
= std::format("{:*<3}", "🤡");
502 VERIFY( sC
== "🤡*" );
504 // Verify that "£" has estimated field width 1, not strlen("£") == 2.
505 std::string sL
= std::format("{:*<3}", "£");
506 VERIFY( sL
== "£**" );
508 // Verify that precision is measured in field width units (column positions)
509 // not bytes. The result should contain complete Unicode characters, not be
510 // truncated in the middle of a multibyte UTF-8 sequence. The string "£" has
511 // field width 1 despite being 2 bytes, and the string "🤡" has field width 2
512 // and so cannot be formatted into a replacement field using .1 precision.
513 std::string sP
= std::format("{:1.1} {:*<1.1}", "£", "🤡");
514 VERIFY( sP
== "£ *" );
515 sP
= std::format("{:*<2.1} {:*<2.1}", "£", "🤡");
516 VERIFY( sP
== "£* **" );
518 // Verify field width handling for extended grapheme clusters,
519 // and that a cluster gets output as a single item, not truncated.
520 std::string sG
= std::format("{:*>2.1}", "\u006f\u0302\u0323!");
521 VERIFY( sG
== "*\u006f\u0302\u0323" );
523 // Examples from P1868R2
524 // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1868r2.html
525 const char* inputs
[][2] = {
527 {"\xC3\x81", " \u00c1"},
528 {"\x41\xCC\x81", " \u0041\u0301"},
529 {"\xc4\xb2", " \u0132"},
530 {"\xce\x94", " \u0394"},
531 {"\xd0\xa9", " \u0429"},
532 {"\xd7\x90", " \u05D0"},
533 {"\xd8\xb4", " \u0634"},
534 {"\xe3\x80\x89", " \u3009"},
535 {"\xe7\x95\x8c", " \u754C"},
536 {"\xf0\x9f\xa6\x84", " \U0001F984"},
537 {"\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d"
538 "\xf0\x9f\x91\xa7\xe2\x80\x8d\xf0\x9f\x91\xa6",
539 " \U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466" }
541 for (auto& input
: inputs
)
543 std::string sA
= std::format("{:>5}", input
[0]);
544 VERIFY( sA
== input
[1] );
553 test_alternate_forms();