]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/std/format/functions/format.cc
RISC-V: Fix avl-type operand index error for ZVBC
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / std / format / functions / format.cc
CommitLineData
1d9454ab 1// { dg-do run { target c++20 } }
51d702f3 2// { dg-add-options no_pch }
1d9454ab
JW
3
4#include <format>
02e86035
JW
5
6#ifndef __cpp_lib_format
7# error "Feature test macro for std::format is missing in <format>"
cdf45e00 8#elif __cpp_lib_format < 202110L
02e86035
JW
9# error "Feature test macro for std::format has wrong value in <format>"
10#endif
11
12#undef __cpp_lib_format
13#include <version>
14#ifndef __cpp_lib_format
15# error "Feature test macro for std::format is missing in <version>"
cdf45e00 16#elif __cpp_lib_format < 202110L
02e86035
JW
17# error "Feature test macro for std::format has wrong value in <version>"
18#endif
19
1d9454ab
JW
20#include <string>
21#include <limits>
22#include <cstdint>
ce86d967 23#include <cstdio>
1d9454ab
JW
24#include <testsuite_hooks.h>
25
26void
27test_no_args()
28{
29 std::string s;
30 s = std::format("disco");
31 VERIFY( s == "disco" );
32
33 s = std::format("}} machine {{ funk }} specialists {{");
34 VERIFY( s == "} machine { funk } specialists {" );
35
36 s = std::format("128bpm }}");
37 VERIFY( s == "128bpm }" );
38}
39
40void
41test_unescaped()
42{
43#ifdef __cpp_exceptions
44 for (auto f : { "{", "}", "{{{", "{{}", "}{", "{{{{{" })
45 try {
46 (void) std::vformat(f, std::make_format_args());
47 VERIFY( false );
48 } catch (const std::format_error& e) {
49 std::string what = e.what();
50 VERIFY( what.find("unmatched") != what.npos );
51 }
52#endif
53}
54
55struct brit_punc : std::numpunct<char>
56{
57 std::string do_grouping() const override { return "\3\3"; }
58 char do_thousands_sep() const override { return ','; }
59 std::string do_truename() const override { return "yes mate"; }
60 std::string do_falsename() const override { return "nah bruv"; }
61};
62
63void
64test_std_examples()
65{
66 using namespace std;
67
68 string s = format("{0}-{{", 8); // value of s is "8-{"
69 VERIFY( s == "8-{" );
70
71 // align
72 {
73 char c = 120;
74 string s0 = format("{:6}", 42);
75 VERIFY(s0 == " 42");
76 string s1 = format("{:6}", 'x');
77 VERIFY(s1 == "x ");
78 string s2 = format("{:*<6}", 'x');
79 VERIFY(s2 == "x*****");
80 string s3 = format("{:*>6}", 'x');
81 VERIFY(s3 == "*****x");
82 string s4 = format("{:*^6}", 'x');
83 VERIFY(s4 == "**x***");
84 string s5 = format("{:6d}", c);
85 VERIFY(s5 == " 120");
86 string s6 = format("{:6}", true);
87 VERIFY(s6 == "true ");
88 }
89
90 // sign
91 {
92 double inf = numeric_limits<double>::infinity();
93 double nan = numeric_limits<double>::quiet_NaN();
94 string s0 = format("{0:},{0:+},{0:-},{0: }", 1);
95 VERIFY(s0 == "1,+1,1, 1");
96 string s1 = format("{0:},{0:+},{0:-},{0: }", -1);
97 VERIFY(s1 == "-1,-1,-1,-1");
98 string s2 = format("{0:},{0:+},{0:-},{0: }", inf);
99 VERIFY(s2 == "inf,+inf,inf, inf");
100 string s3 = format("{0:},{0:+},{0:-},{0: }", nan);
101 VERIFY(s3 == "nan,+nan,nan, nan");
102 }
103
104 // alternate form and zero fill
105 {
106 char c = 120;
107 string s1 = format("{:+06d}", c);
108 VERIFY(s1 == "+00120");
109 string s2 = format("{:#06x}", 0xa);
110 VERIFY(s2 == "0x000a");
111 string s3 = format("{:<06}", -42);
112 VERIFY(s3 == "-42 "); // 0 is ignored because of < alignment
113 }
114
115 // integer presentation types
116 {
117 // Change global locale so "{:L}" adds digit separators.
118 std::locale::global(std::locale({}, new brit_punc));
119
120 string s0 = format("{}", 42);
121 VERIFY(s0 == "42");
122 string s1 = format("{0:b} {0:d} {0:o} {0:x}", 42);
123 VERIFY(s1 == "101010 42 52 2a");
124 string s2 = format("{0:#x} {0:#X}", 42);
125 VERIFY(s2 == "0x2a 0X2A");
126 string s3 = format("{:L}", 1234);
127 VERIFY(s3 == "1,234");
128
48e21e87
JW
129 // Test locale's "byte-and-a-half" grouping (Imperial word? tribble?).
130 string s4 = format("{:#Lx}", 0xfffff);
131 VERIFY(s4 == "0xff,fff");
132
1d9454ab
JW
133 // Restore
134 std::locale::global(std::locale::classic());
135 }
136}
137
138void
139test_alternate_forms()
140{
141 std::string s;
142
143 s = std::format("{0:#b} {0:+#B} {0:#o} {0:#x} {0:+#X} {0: #d}", 42);
144 VERIFY( s == "0b101010 +0B101010 052 0x2a +0X2A 42" );
145 s = std::format("{0:#b} {0:+#B} {0:#o} {0:#x} {0:+#X} {0: #d}", 0);
146 VERIFY( s == "0b0 +0B0 0 0x0 +0X0 0" );
147
148 s = std::format("{0:+#012g} {0:+#014g} {0:+#014g}", 1234.0);
149 VERIFY( s == "+00001234.00 +0000001234.00 +0000001234.00" );
150 s = std::format("{0:+#0{1}g} {0:+#0{2}g} {0:+#0{2}g}", 1234.5, 12, 14);
151 VERIFY( s == "+00001234.50 +0000001234.50 +0000001234.50" );
152
153 s = std::format("{:#.2g}", -0.0);
154 VERIFY( s == "-0.0" );
50bc490c
JW
155
156 // PR libstdc++/108046
157 s = std::format("{0:#.0} {0:#.1} {0:#.0g}", 10.0);
158 VERIFY( s == "1.e+01 1.e+01 1.e+01" );
1d9454ab
JW
159}
160
d07bce47
JW
161void
162test_infnan()
163{
164 double inf = std::numeric_limits<double>::infinity();
165 double nan = std::numeric_limits<double>::quiet_NaN();
166 std::string s;
167 s = std::format("{0} {0:e} {0:E} {0:f} {0:F} {0:g} {0:G} {0:a} {0:A}", inf);
168 VERIFY( s == "inf inf INF inf INF inf INF inf INF" );
169 s = std::format("{0} {0:e} {0:E} {0:f} {0:F} {0:g} {0:G} {0:a} {0:A}", nan);
170 VERIFY( s == "nan nan NAN nan NAN nan NAN nan NAN" );
171}
172
1d9454ab
JW
173struct euro_punc : std::numpunct<char>
174{
175 std::string do_grouping() const override { return "\3\3"; }
176 char do_thousands_sep() const override { return '.'; }
177 char do_decimal_point() const override { return ','; }
178};
179
180void
181test_locale()
182{
183 // The default C locale.
184 std::locale cloc = std::locale::classic();
185 // A custom locale using comma digit separators.
186 std::locale bloc(cloc, new brit_punc);
187 // A custom locale using period digit separators.
188 std::locale eloc(cloc, new euro_punc);
189
190 std::string s;
191
192 // Change the global locale:
193 std::locale::global(bloc);
194 // Format using the global locale:
195 s = std::format("{0:L} {0:Lx} {0:Lb}", 12345);
196 VERIFY( s == "12,345 3,039 11,000,000,111,001" );
197 s = std::format("{0:L} {0:.7Lg} {0:La}", 12345.6789);
198 VERIFY( s == "12,345.6789 12,345.68 1.81cd6e631f8a1p+13" );
199
200 s = std::format("{0:s} {0:L} {1:Ls} {0:Ld}", true, false);
201 VERIFY( s == "true yes mate nah bruv 1" );
202
203 // Format using a specific locale:
204 s = std::format(eloc, "{0:L} {0:Lx} {0:Lb}", 12345);
205 VERIFY( s == "12.345 3.039 11.000.000.111.001" );
206 s = std::format(eloc, "{0:L} {0:.7LG} {0:La}", 12345.6789);
207 VERIFY( s == "12.345,6789 12.345,68 1,81cd6e631f8a1p+13" );
208
209 s = std::format(eloc, "{0:#Lg} {0:+#.3Lg} {0:#08.4Lg}", -1234.);
210 VERIFY( s == "-1.234,00 -1,23e+03 -01.234," );
211
f48a5423
JW
212 s = std::format(cloc, "{:05L}", -1.0); // PR libstdc++/110968
213 VERIFY( s == "-0001" );
214
1d9454ab
JW
215 // Restore
216 std::locale::global(cloc);
217}
218
219void
220test_width()
221{
222 std::string s;
223
224 s = std::format("{:4}", "");
225 VERIFY( s == " " );
226 s = std::format("{:{}}", "", 3);
227 VERIFY( s == " " );
628ba410
JW
228 s = std::format("{:{}}|{:{}}", 1, 2, 3, 4);
229 VERIFY( s == " 1| 3" );
1d9454ab
JW
230 s = std::format("{1:{0}}", 2, "");
231 VERIFY( s == " " );
232 s = std::format("{:03}", 9);
233 VERIFY( s == "009" );
234
235 s = std::format("DR {0:{1}}: allow width {1} from arg-id", 3721, 0);
236 VERIFY( s == "DR 3721: allow width 0 from arg-id" );
237
238 try {
239 s = std::format("Negative width is an error: {0:{1}}", 123, -1);
240 VERIFY(false);
241 } catch (const std::format_error&) {
242 }
243
244 try {
245 auto args = std::make_format_args(false, true);
246 s = std::vformat("DR 3720: restrict type of width arg-id {0:{1}}", args);
247 VERIFY(false);
248 } catch (const std::format_error&) {
249 }
250
251 try {
252 auto args = std::make_format_args('?', '!');
253 s = std::vformat("DR 3720: restrict type of width arg-id {0:{1}}", args);
254 VERIFY(false);
255 } catch (const std::format_error&) {
256 }
257}
258
52de6aa1
JW
259void
260test_char()
261{
262 std::string s;
263
264 s = std::format("{}", 'a');
265 VERIFY( s == "a" );
266
267 s = std::format("{:c} {:d} {:o}", 'b', '\x17', '\x3f');
268 VERIFY( s == "b 23 77" );
269
270 s = std::format("{:#d} {:#o}", '\x17', '\x3f');
271 VERIFY( s == "23 077" );
272
273 s = std::format("{:04d} {:04o}", '\x17', '\x3f');
274 VERIFY( s == "0023 0077" );
275
276 s = std::format("{:b} {:B} {:#b} {:#B}", '\xff', '\xa0', '\x17', '\x3f');
277 if constexpr (std::is_unsigned_v<char>)
278 VERIFY( s == "11111111 10100000 0b10111 0B111111" );
279 else
280 VERIFY( s == "-1 -1100000 0b10111 0B111111" );
281
282 s = std::format("{:x} {:#x} {:#X}", '\x12', '\x34', '\x45');
283 VERIFY( s == "12 0x34 0X45" );
284}
285
1d9454ab
JW
286void
287test_wchar()
288{
289 using namespace std::literals;
290 std::wstring s;
291
52de6aa1
JW
292 s = std::format(L"{}", L'a');
293 VERIFY( s == L"a" );
294
1d9454ab
JW
295 s = std::format(L"{} {} {} {} {} {}", L'0', 1, 2LL, 3.4, L"five", L"six"s);
296 VERIFY( s == L"0 1 2 3.4 five six" );
297
298 std::locale loc;
299 s = std::format(loc, L"{:L} {:.3s}{:Lc}", true, L"data"sv, '.');
300 VERIFY( s == L"true dat." );
4a2b2625
JW
301
302 s = std::format(L"{}", 0.0625);
303 VERIFY( s == L"0.0625" );
304 s = std::format(L"{}", 0.25);
305 VERIFY( s == L"0.25" );
023a62b7
JW
306 s = std::format(L"{:+a} {:A}", 0x1.23p45, -0x1.abcdefp-15);
307 VERIFY( s == L"+1.23p+45 -1.ABCDEFP-15" );
308
309 double inf = std::numeric_limits<double>::infinity();
310 double nan = std::numeric_limits<double>::quiet_NaN();
311 s = std::format(L"{0} {0:F} {1} {1:E}", -inf, -nan);
312 VERIFY( s == L"-inf -INF -nan -NAN" );
313
314 s = std::format(L"{0:#b} {0:#B} {0:#x} {0:#X}", 99);
315 VERIFY( s == L"0b1100011 0B1100011 0x63 0X63" );
1d9454ab
JW
316}
317
318void
319test_minmax()
320{
c68c468e 321 auto check = []<typename T, typename U = std::make_unsigned_t<T>>(T, U = 0) {
1d9454ab
JW
322 const int digits = std::numeric_limits<T>::digits;
323 const std::string zeros(digits, '0');
324 const std::string ones(digits, '1');
325 auto s = std::format("{:b}" , std::numeric_limits<T>::min());
326 VERIFY( s == "-1" + zeros );
327 s = std::format("{:b}" , std::numeric_limits<T>::max());
328 VERIFY( s == ones );
1d9454ab
JW
329 s = std::format("{:0{}b}" , std::numeric_limits<U>::min(), digits + 1);
330 VERIFY( s == '0' + zeros );
331 s = std::format("{:b}" , std::numeric_limits<U>::max());
332 VERIFY( s == '1' + ones );
333 };
334 check(std::int8_t(0));
335 check(std::int16_t(0));
336 check(std::int32_t(0));
337 check(std::int64_t(0));
338#ifdef __SIZEOF_INT128__
c68c468e
JW
339 // std::make_unsigned_t<__int128> is invalid for strict -std=c++20 mode,
340 // so pass a second argument of the unsigned type.
341 check(__int128(0), (unsigned __int128)(0));
1d9454ab
JW
342#endif
343}
344
345void
346test_p1652r1() // printf corner cases in std::format
347{
348 std::string s;
349
350 // Problem 1: "#o" specification should not print 0 as "00"
351 s = std::format("{:#o}", 0);
352 VERIFY( s == "0" );
353
354 // Problem 2: 'c' should be able to print 65 as "A" (ASCII)
355 int c = 'A';
356 s = std::format("{:c}", c);
357 VERIFY( s == "A" );
358
359 // Problem 3: "-000nan" is not a floating point value
360 double nan = std::numeric_limits<double>::quiet_NaN();
361 try {
362 s = std::vformat("{:0=6}", std::make_format_args(nan));
363 VERIFY( false );
364 } catch (const std::format_error&) {
365 }
366
367 s = std::format("{:06}", nan);
368 VERIFY( s == " nan" );
369
370 // Problem 4: bool needs a type format specifier
371 s = std::format("{:s}", true);
372 VERIFY( s == "true" );
373
374 // Problem 5: double does not roundtrip float
375 s = std::format("{}", 3.31f);
376 VERIFY( s == "3.31" );
377}
378
628ba410
JW
379void
380test_pointer()
381{
382 void* p = nullptr;
383 const void* pc = p;
384 std::string s, str_int;
385
52de6aa1
JW
386 s = std::format("{}", p);
387 VERIFY( s == "0x0" );
388
628ba410
JW
389 s = std::format("{} {} {}", p, pc, nullptr);
390 VERIFY( s == "0x0 0x0 0x0" );
391 s = std::format("{:p} {:p} {:p}", p, pc, nullptr);
392 VERIFY( s == "0x0 0x0 0x0" );
393 s = std::format("{:4},{:5},{:6}", p, pc, nullptr); // width
394 VERIFY( s == " 0x0, 0x0, 0x0" );
395 s = std::format("{:<4},{:>5},{:^7}", p, pc, nullptr); // align+width
396 VERIFY( s == "0x0 , 0x0, 0x0 " );
397 s = std::format("{:o<4},{:o>5},{:o^7}", p, pc, nullptr); // fill+align+width
398 VERIFY( s == "0x0o,oo0x0,oo0x0oo" );
399
400 pc = p = &s;
401 str_int = std::format("{:#x}", reinterpret_cast<std::uintptr_t>(p));
402 s = std::format("{} {} {}", p, pc, nullptr);
403 VERIFY( s == (str_int + ' ' + str_int + " 0x0") );
404 str_int = std::format("{:#20x}", reinterpret_cast<std::uintptr_t>(p));
405 s = std::format("{:20} {:20p}", p, pc);
406 VERIFY( s == (str_int + ' ' + str_int) );
407
408#if __cplusplus > 202302L || ! defined __STRICT_ANSI__
409 // P2510R3 Formatting pointers
410 s = std::format("{:06} {:07P} {:08p}", (void*)0, (const void*)0, nullptr);
411 VERIFY( s == "0x0000 0X00000 0x000000" );
412 str_int = std::format("{:#016x}", reinterpret_cast<std::uintptr_t>(p));
413 s = std::format("{:016} {:016}", p, pc);
414 VERIFY( s == (str_int + ' ' + str_int) );
415 str_int = std::format("{:#016X}", reinterpret_cast<std::uintptr_t>(p));
416 s = std::format("{:016P} {:016P}", p, pc);
417 VERIFY( s == (str_int + ' ' + str_int) );
418#endif
419}
420
52de6aa1
JW
421void
422test_bool()
423{
424 std::string s;
425
426 s = std::format("{}", true);
427 VERIFY( s == "true" );
428 s = std::format("{:} {:s}", true, false);
429 VERIFY( s == "true false" );
430 s = std::format("{:b} {:#b}", true, false);
431 VERIFY( s == "1 0b0" );
432 s = std::format("{:B} {:#B}", false, true);
433 VERIFY( s == "0 0B1" );
434 s = std::format("{:d} {:#d}", false, true);
435 VERIFY( s == "0 1" );
436 s = std::format("{:o} {:#o} {:#o}", false, true, false);
437 VERIFY( s == "0 01 0" );
438 s = std::format("{:x} {:#x} {:#X}", false, true, false);
439 VERIFY( s == "0 0x1 0X0" );
440}
441
1d9454ab
JW
442int main()
443{
444 test_no_args();
445 test_unescaped();
446 test_std_examples();
447 test_alternate_forms();
448 test_locale();
449 test_width();
52de6aa1 450 test_char();
1d9454ab
JW
451 test_wchar();
452 test_minmax();
453 test_p1652r1();
628ba410 454 test_pointer();
52de6aa1 455 test_bool();
1d9454ab 456}