[flang] Accept polymorphic component element in storage_size
[llvm-project.git] / libc / test / src / stdio / printf_core / parser_test.cpp
blobb0a1cfc5b8a00a309c7a46702a6b9b0f50b62052
1 //===-- Unittests for the printf Parser -----------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "src/__support/CPP/bit.h"
10 #include "src/__support/CPP/string_view.h"
11 #include "src/__support/arg_list.h"
12 #include "src/stdio/printf_core/parser.h"
14 #include <stdarg.h>
16 #include "test/UnitTest/PrintfMatcher.h"
17 #include "test/UnitTest/Test.h"
19 using __llvm_libc::cpp::string_view;
21 void init(const char *__restrict str, ...) {
22 va_list vlist;
23 va_start(vlist, str);
24 __llvm_libc::internal::ArgList v(vlist);
25 va_end(vlist);
27 __llvm_libc::printf_core::Parser parser(str, v);
30 void evaluate(__llvm_libc::printf_core::FormatSection *format_arr,
31 const char *__restrict str, ...) {
32 va_list vlist;
33 va_start(vlist, str);
34 __llvm_libc::internal::ArgList v(vlist);
35 va_end(vlist);
37 __llvm_libc::printf_core::Parser parser(str, v);
39 for (auto cur_section = parser.get_next_section();
40 !cur_section.raw_string.empty();
41 cur_section = parser.get_next_section()) {
42 *format_arr = cur_section;
43 ++format_arr;
47 TEST(LlvmLibcPrintfParserTest, Constructor) { init("test", 1, 2); }
49 TEST(LlvmLibcPrintfParserTest, EvalRaw) {
50 __llvm_libc::printf_core::FormatSection format_arr[10];
51 const char *str = "test";
52 evaluate(format_arr, str);
54 __llvm_libc::printf_core::FormatSection expected;
55 expected.has_conv = false;
57 expected.raw_string = {str, 4};
59 ASSERT_PFORMAT_EQ(expected, format_arr[0]);
60 // TODO: add checks that the format_arr after the last one has length 0
63 TEST(LlvmLibcPrintfParserTest, EvalSimple) {
64 __llvm_libc::printf_core::FormatSection format_arr[10];
65 const char *str = "test %% test";
66 evaluate(format_arr, str);
68 __llvm_libc::printf_core::FormatSection expected0, expected1, expected2;
69 expected0.has_conv = false;
71 expected0.raw_string = {str, 5};
73 ASSERT_PFORMAT_EQ(expected0, format_arr[0]);
75 expected1.has_conv = true;
77 expected1.raw_string = {str + 5, 2};
78 expected1.conv_name = '%';
80 ASSERT_PFORMAT_EQ(expected1, format_arr[1]);
82 expected2.has_conv = false;
84 expected2.raw_string = {str + 7, 5};
86 ASSERT_PFORMAT_EQ(expected2, format_arr[2]);
89 TEST(LlvmLibcPrintfParserTest, EvalOneArg) {
90 __llvm_libc::printf_core::FormatSection format_arr[10];
91 const char *str = "%d";
92 int arg1 = 12345;
93 evaluate(format_arr, str, arg1);
95 __llvm_libc::printf_core::FormatSection expected;
96 expected.has_conv = true;
98 expected.raw_string = {str, 2};
99 expected.conv_val_raw = arg1;
100 expected.conv_name = 'd';
102 ASSERT_PFORMAT_EQ(expected, format_arr[0]);
105 TEST(LlvmLibcPrintfParserTest, EvalBadArg) {
106 __llvm_libc::printf_core::FormatSection format_arr[10];
107 const char *str = "%\0abc";
108 int arg1 = 12345;
109 evaluate(format_arr, str, arg1);
111 __llvm_libc::printf_core::FormatSection expected;
112 expected.has_conv = false;
113 expected.raw_string = {str, 1};
115 ASSERT_PFORMAT_EQ(expected, format_arr[0]);
118 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithFlags) {
119 __llvm_libc::printf_core::FormatSection format_arr[10];
120 const char *str = "%+-0 #d";
121 int arg1 = 12345;
122 evaluate(format_arr, str, arg1);
124 __llvm_libc::printf_core::FormatSection expected;
125 expected.has_conv = true;
127 expected.raw_string = {str, 7};
128 expected.flags = static_cast<__llvm_libc::printf_core::FormatFlags>(
129 __llvm_libc::printf_core::FormatFlags::FORCE_SIGN |
130 __llvm_libc::printf_core::FormatFlags::LEFT_JUSTIFIED |
131 __llvm_libc::printf_core::FormatFlags::LEADING_ZEROES |
132 __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX |
133 __llvm_libc::printf_core::FormatFlags::ALTERNATE_FORM);
134 expected.conv_val_raw = arg1;
135 expected.conv_name = 'd';
137 ASSERT_PFORMAT_EQ(expected, format_arr[0]);
140 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithWidth) {
141 __llvm_libc::printf_core::FormatSection format_arr[10];
142 const char *str = "%12d";
143 int arg1 = 12345;
144 evaluate(format_arr, str, arg1);
146 __llvm_libc::printf_core::FormatSection expected;
147 expected.has_conv = true;
149 expected.raw_string = {str, 4};
150 expected.min_width = 12;
151 expected.conv_val_raw = arg1;
152 expected.conv_name = 'd';
154 ASSERT_PFORMAT_EQ(expected, format_arr[0]);
157 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithPrecision) {
158 __llvm_libc::printf_core::FormatSection format_arr[10];
159 const char *str = "%.34d";
160 int arg1 = 12345;
161 evaluate(format_arr, str, arg1);
163 __llvm_libc::printf_core::FormatSection expected;
164 expected.has_conv = true;
166 expected.raw_string = {str, 5};
167 expected.precision = 34;
168 expected.conv_val_raw = arg1;
169 expected.conv_name = 'd';
171 ASSERT_PFORMAT_EQ(expected, format_arr[0]);
174 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithTrivialPrecision) {
175 __llvm_libc::printf_core::FormatSection format_arr[10];
176 const char *str = "%.d";
177 int arg1 = 12345;
178 evaluate(format_arr, str, arg1);
180 __llvm_libc::printf_core::FormatSection expected;
181 expected.has_conv = true;
183 expected.raw_string = {str, 3};
184 expected.precision = 0;
185 expected.conv_val_raw = arg1;
186 expected.conv_name = 'd';
188 ASSERT_PFORMAT_EQ(expected, format_arr[0]);
191 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithShortLengthModifier) {
192 __llvm_libc::printf_core::FormatSection format_arr[10];
193 const char *str = "%hd";
194 int arg1 = 12345;
195 evaluate(format_arr, str, arg1);
197 __llvm_libc::printf_core::FormatSection expected;
198 expected.has_conv = true;
200 expected.raw_string = {str, 3};
201 expected.length_modifier = __llvm_libc::printf_core::LengthModifier::h;
202 expected.conv_val_raw = arg1;
203 expected.conv_name = 'd';
205 ASSERT_PFORMAT_EQ(expected, format_arr[0]);
208 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithLongLengthModifier) {
209 __llvm_libc::printf_core::FormatSection format_arr[10];
210 const char *str = "%lld";
211 long long arg1 = 12345;
212 evaluate(format_arr, str, arg1);
214 __llvm_libc::printf_core::FormatSection expected;
215 expected.has_conv = true;
217 expected.raw_string = {str, 4};
218 expected.length_modifier = __llvm_libc::printf_core::LengthModifier::ll;
219 expected.conv_val_raw = arg1;
220 expected.conv_name = 'd';
222 ASSERT_PFORMAT_EQ(expected, format_arr[0]);
225 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithAllOptions) {
226 __llvm_libc::printf_core::FormatSection format_arr[10];
227 const char *str = "% -056.78jd";
228 intmax_t arg1 = 12345;
229 evaluate(format_arr, str, arg1);
231 __llvm_libc::printf_core::FormatSection expected;
232 expected.has_conv = true;
234 expected.raw_string = {str, 11};
235 expected.flags = static_cast<__llvm_libc::printf_core::FormatFlags>(
236 __llvm_libc::printf_core::FormatFlags::LEFT_JUSTIFIED |
237 __llvm_libc::printf_core::FormatFlags::LEADING_ZEROES |
238 __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX);
239 expected.min_width = 56;
240 expected.precision = 78;
241 expected.length_modifier = __llvm_libc::printf_core::LengthModifier::j;
242 expected.conv_val_raw = arg1;
243 expected.conv_name = 'd';
245 ASSERT_PFORMAT_EQ(expected, format_arr[0]);
248 TEST(LlvmLibcPrintfParserTest, EvalThreeArgs) {
249 __llvm_libc::printf_core::FormatSection format_arr[10];
250 const char *str = "%d%f%s";
251 int arg1 = 12345;
252 double arg2 = 123.45;
253 const char *arg3 = "12345";
254 evaluate(format_arr, str, arg1, arg2, arg3);
256 __llvm_libc::printf_core::FormatSection expected0, expected1, expected2;
257 expected0.has_conv = true;
259 expected0.raw_string = {str, 2};
260 expected0.conv_val_raw = arg1;
261 expected0.conv_name = 'd';
263 ASSERT_PFORMAT_EQ(expected0, format_arr[0]);
265 expected1.has_conv = true;
267 expected1.raw_string = {str + 2, 2};
268 expected1.conv_val_raw = __llvm_libc::cpp::bit_cast<uint64_t>(arg2);
269 expected1.conv_name = 'f';
271 ASSERT_PFORMAT_EQ(expected1, format_arr[1]);
273 expected2.has_conv = true;
275 expected2.raw_string = {str + 4, 2};
276 expected2.conv_val_ptr = const_cast<char *>(arg3);
277 expected2.conv_name = 's';
279 ASSERT_PFORMAT_EQ(expected2, format_arr[2]);
282 #ifndef LIBC_COPT_PRINTF_DISABLE_INDEX_MODE
284 TEST(LlvmLibcPrintfParserTest, IndexModeOneArg) {
285 __llvm_libc::printf_core::FormatSection format_arr[10];
286 const char *str = "%1$d";
287 int arg1 = 12345;
288 evaluate(format_arr, str, arg1);
290 __llvm_libc::printf_core::FormatSection expected;
291 expected.has_conv = true;
293 expected.raw_string = {str, 4};
294 expected.conv_val_raw = arg1;
295 expected.conv_name = 'd';
297 ASSERT_PFORMAT_EQ(expected, format_arr[0]);
300 TEST(LlvmLibcPrintfParserTest, IndexModeThreeArgsSequential) {
301 __llvm_libc::printf_core::FormatSection format_arr[10];
302 const char *str = "%1$d%2$f%3$s";
303 int arg1 = 12345;
304 double arg2 = 123.45;
305 const char *arg3 = "12345";
306 evaluate(format_arr, str, arg1, arg2, arg3);
308 __llvm_libc::printf_core::FormatSection expected0, expected1, expected2;
309 expected0.has_conv = true;
311 expected0.raw_string = {str, 4};
312 expected0.conv_val_raw = arg1;
313 expected0.conv_name = 'd';
315 ASSERT_PFORMAT_EQ(expected0, format_arr[0]);
317 expected1.has_conv = true;
319 expected1.raw_string = {str + 4, 4};
320 expected1.conv_val_raw = __llvm_libc::cpp::bit_cast<uint64_t>(arg2);
321 expected1.conv_name = 'f';
323 ASSERT_PFORMAT_EQ(expected1, format_arr[1]);
325 expected2.has_conv = true;
327 expected2.raw_string = {str + 8, 4};
328 expected2.conv_val_ptr = const_cast<char *>(arg3);
329 expected2.conv_name = 's';
331 ASSERT_PFORMAT_EQ(expected2, format_arr[2]);
334 TEST(LlvmLibcPrintfParserTest, IndexModeThreeArgsReverse) {
335 __llvm_libc::printf_core::FormatSection format_arr[10];
336 const char *str = "%3$d%2$f%1$s";
337 int arg1 = 12345;
338 double arg2 = 123.45;
339 const char *arg3 = "12345";
340 evaluate(format_arr, str, arg3, arg2, arg1);
342 __llvm_libc::printf_core::FormatSection expected0, expected1, expected2;
343 expected0.has_conv = true;
345 expected0.raw_string = {str, 4};
346 expected0.conv_val_raw = arg1;
347 expected0.conv_name = 'd';
349 ASSERT_PFORMAT_EQ(expected0, format_arr[0]);
351 expected1.has_conv = true;
353 expected1.raw_string = {str + 4, 4};
354 expected1.conv_val_raw = __llvm_libc::cpp::bit_cast<uint64_t>(arg2);
355 expected1.conv_name = 'f';
357 ASSERT_PFORMAT_EQ(expected1, format_arr[1]);
359 expected2.has_conv = true;
361 expected2.raw_string = {str + 8, 4};
362 expected2.conv_val_ptr = const_cast<char *>(arg3);
363 expected2.conv_name = 's';
365 ASSERT_PFORMAT_EQ(expected2, format_arr[2]);
368 TEST(LlvmLibcPrintfParserTest, IndexModeTenArgsRandom) {
369 __llvm_libc::printf_core::FormatSection format_arr[10];
370 const char *str = "%6$d%3$d%7$d%2$d%8$d%1$d%4$d%9$d%5$d%10$d";
371 int args[10] = {6, 4, 2, 7, 9, 1, 3, 5, 8, 10};
372 evaluate(format_arr, str, args[0], args[1], args[2], args[3], args[4],
373 args[5], args[6], args[7], args[8], args[9]);
375 for (size_t i = 0; i < 10; ++i) {
376 __llvm_libc::printf_core::FormatSection expected;
377 expected.has_conv = true;
379 expected.raw_string = {str + (4 * i),
380 static_cast<size_t>(4 + (i >= 9 ? 1 : 0))};
381 expected.conv_val_raw = i + 1;
382 expected.conv_name = 'd';
383 EXPECT_PFORMAT_EQ(expected, format_arr[i]);
387 TEST(LlvmLibcPrintfParserTest, IndexModeComplexParsing) {
388 __llvm_libc::printf_core::FormatSection format_arr[10];
389 const char *str = "normal text %3$llu %% %2$ *4$f %2$ .*4$f %1$1.1c";
390 char arg1 = '1';
391 double arg2 = 123.45;
392 unsigned long long arg3 = 12345;
393 int arg4 = 10;
394 evaluate(format_arr, str, arg1, arg2, arg3, arg4);
396 __llvm_libc::printf_core::FormatSection expected0, expected1, expected2,
397 expected3, expected4, expected5, expected6, expected7, expected8,
398 expected9;
400 expected0.has_conv = false;
402 expected0.raw_string = {str, 12};
404 EXPECT_PFORMAT_EQ(expected0, format_arr[0]);
406 expected1.has_conv = true;
408 expected1.raw_string = {str + 12, 6};
409 expected1.length_modifier = __llvm_libc::printf_core::LengthModifier::ll;
410 expected1.conv_val_raw = arg3;
411 expected1.conv_name = 'u';
413 EXPECT_PFORMAT_EQ(expected1, format_arr[1]);
415 expected2.has_conv = false;
417 expected2.raw_string = {str + 18, 1};
419 EXPECT_PFORMAT_EQ(expected2, format_arr[2]);
421 expected3.has_conv = true;
423 expected3.raw_string = {str + 19, 2};
424 expected3.conv_name = '%';
426 EXPECT_PFORMAT_EQ(expected3, format_arr[3]);
428 expected4.has_conv = false;
430 expected4.raw_string = {str + 21, 1};
432 EXPECT_PFORMAT_EQ(expected4, format_arr[4]);
434 expected5.has_conv = true;
436 expected5.raw_string = {str + 22, 8};
437 expected5.flags = __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX;
438 expected5.min_width = arg4;
439 expected5.conv_val_raw = __llvm_libc::cpp::bit_cast<uint64_t>(arg2);
440 expected5.conv_name = 'f';
442 EXPECT_PFORMAT_EQ(expected5, format_arr[5]);
444 expected6.has_conv = false;
446 expected6.raw_string = {str + 30, 1};
448 EXPECT_PFORMAT_EQ(expected6, format_arr[6]);
450 expected7.has_conv = true;
452 expected7.raw_string = {str + 31, 9};
453 expected7.flags = __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX;
454 expected7.precision = arg4;
455 expected7.conv_val_raw = __llvm_libc::cpp::bit_cast<uint64_t>(arg2);
456 expected7.conv_name = 'f';
458 EXPECT_PFORMAT_EQ(expected7, format_arr[7]);
460 expected8.has_conv = false;
462 expected8.raw_string = {str + 40, 1};
464 EXPECT_PFORMAT_EQ(expected8, format_arr[8]);
466 expected9.has_conv = true;
468 expected9.raw_string = {str + 41, 7};
469 expected9.min_width = 1;
470 expected9.precision = 1;
471 expected9.conv_val_raw = arg1;
472 expected9.conv_name = 'c';
474 EXPECT_PFORMAT_EQ(expected9, format_arr[9]);
477 TEST(LlvmLibcPrintfParserTest, IndexModeGapCheck) {
478 __llvm_libc::printf_core::FormatSection format_arr[10];
479 const char *str = "%1$d%2$d%4$d";
480 int arg1 = 1;
481 int arg2 = 2;
482 int arg3 = 3;
483 int arg4 = 4;
485 evaluate(format_arr, str, arg1, arg2, arg3, arg4);
487 __llvm_libc::printf_core::FormatSection expected0, expected1, expected2;
489 expected0.has_conv = true;
490 expected0.raw_string = {str, 4};
491 expected0.conv_val_raw = arg1;
492 expected0.conv_name = 'd';
494 EXPECT_PFORMAT_EQ(expected0, format_arr[0]);
496 expected1.has_conv = true;
497 expected1.raw_string = {str + 4, 4};
498 expected1.conv_val_raw = arg2;
499 expected1.conv_name = 'd';
501 EXPECT_PFORMAT_EQ(expected1, format_arr[1]);
503 expected2.has_conv = false;
504 expected2.raw_string = {str + 8, 4};
506 EXPECT_PFORMAT_EQ(expected2, format_arr[2]);
509 TEST(LlvmLibcPrintfParserTest, IndexModeTrailingPercentCrash) {
510 __llvm_libc::printf_core::FormatSection format_arr[10];
511 const char *str = "%2$d%";
512 evaluate(format_arr, str, 1, 2);
514 __llvm_libc::printf_core::FormatSection expected0, expected1;
515 expected0.has_conv = false;
517 expected0.raw_string = {str, 4};
518 EXPECT_PFORMAT_EQ(expected0, format_arr[0]);
520 expected1.has_conv = false;
522 expected1.raw_string = {str + 4, 1};
523 EXPECT_PFORMAT_EQ(expected1, format_arr[1]);
526 #endif // LIBC_COPT_PRINTF_DISABLE_INDEX_MODE