Skip to content

[libc++][format] Handle range-underlying-spec #81914

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

poyaoc97
Copy link
Member

An immediate colon signifeis that the range-format-spec contains only range-underlying-spec.

This patch allows this code to compile and run:

std::println("{::<<9?}", std::span<const char>{"Hello", sizeof "Hello"});

An immediate colon signifeis that the range-format-spec contains
only range-underlying-spec.

This patch allows this code to compile and run:
```c++
std::println("{::<<9?}", std::span<const char>{"Hello", sizeof "Hello"});
```
@poyaoc97 poyaoc97 added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Feb 15, 2024
@poyaoc97 poyaoc97 requested a review from mordante February 15, 2024 20:28
@llvmbot
Copy link
Member

llvmbot commented Feb 15, 2024

@llvm/pr-subscribers-libcxx

Author: Po-yao Chang (poyaoc97)

Changes

An immediate colon signifeis that the range-format-spec contains only range-underlying-spec.

This patch allows this code to compile and run:

std::println("{::&lt;&lt;9?}", std::span&lt;const char&gt;{"Hello", sizeof "Hello"});

Patch is 36.85 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/81914.diff

8 Files Affected:

  • (modified) libcxx/include/__format/parser_std_format_spec.h (+8-5)
  • (modified) libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h (+2-9)
  • (modified) libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h (-1)
  • (modified) libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.tests.h (-15)
  • (modified) libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.tests.h (+2-17)
  • (modified) libcxx/test/std/utilities/format/format.range/format.range.fmtstr/format.functions.tests.h (-2)
  • (modified) libcxx/test/std/utilities/format/format.range/format.range.formatter/format.functions.tests.h (+2-15)
  • (modified) libcxx/test/std/utilities/format/format.tuple/format.functions.tests.h (-5)
diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h
index 370b28a22bba77..ff415e5155f64e 100644
--- a/libcxx/include/__format/parser_std_format_spec.h
+++ b/libcxx/include/__format/parser_std_format_spec.h
@@ -143,9 +143,10 @@ struct __fields {
   // formatters use the colon to mark the beginning of the
   // underlying-format-spec. To avoid parsing ambiguities these formatter
   // specializations prohibit the use of the colon as a fill character.
-  uint16_t __use_range_fill_ : 1 {false};
-  uint16_t __clear_brackets_ : 1 {false};
-  uint16_t __consume_all_    : 1 {false};
+  uint16_t __use_range_fill_            : 1 {false};
+  uint16_t __clear_brackets_            : 1 {false};
+  uint16_t __consume_all_               : 1 {false};
+  uint16_t __has_range_underlying_spec_ : 1 {false};
 };
 
 // By not placing this constant in the formatter class it's not duplicated for
@@ -171,7 +172,8 @@ inline constexpr __fields __fields_pointer{.__zero_padding_ = true, .__type_ = t
 
 #  if _LIBCPP_STD_VER >= 23
 inline constexpr __fields __fields_tuple{.__use_range_fill_ = true, .__clear_brackets_ = true};
-inline constexpr __fields __fields_range{.__use_range_fill_ = true, .__clear_brackets_ = true};
+inline constexpr __fields __fields_range{
+    .__use_range_fill_ = true, .__clear_brackets_ = true, .__has_range_underlying_spec_ = true};
 inline constexpr __fields __fields_fill_align_width{};
 #  endif
 
@@ -355,7 +357,8 @@ class _LIBCPP_TEMPLATE_VIS __parser {
   _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator __parse(_ParseContext& __ctx, __fields __fields) {
     auto __begin = __ctx.begin();
     auto __end   = __ctx.end();
-    if (__begin == __end || *__begin == _CharT('}'))
+    if (__begin == __end || *__begin == _CharT('}') ||
+        (__fields.__has_range_underlying_spec_ && *__begin == _CharT(':')))
       return __begin;
 
     if (__parse_fill_align(__begin, __end, __fields.__use_range_fill_) && __begin == __end)
diff --git a/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h b/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h
index 05de1bb12dfa5a..9dab5ac98a7d5c 100644
--- a/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h
+++ b/libcxx/test/std/containers/container.adaptors/container.adaptors.format/format.functions.tests.h
@@ -53,7 +53,6 @@ void test_char_default(TestFunction check, ExceptionTest check_exception, auto&&
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -153,7 +152,7 @@ void test_char_string(TestFunction check, ExceptionTest check_exception, auto&&
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<s}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<s}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<s}"), input);
+  check_exception("The type option contains an invalid value for a character formatting argument", SV("{::<s}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-s}"), input);
@@ -206,7 +205,7 @@ void test_char_escaped_string(TestFunction check, ExceptionTest check_exception,
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<?s}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<?s}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<?s}"), input);
+  check_exception("The format specifier should consume the input or end with a '}'", SV("{::<?s}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-?s}"), input);
@@ -324,7 +323,6 @@ void test_bool(TestFunction check, ExceptionTest check_exception, auto&& input)
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -440,7 +438,6 @@ void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -550,7 +547,6 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception, auto
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -688,7 +684,6 @@ void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& inpu
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -798,7 +793,6 @@ void test_string(TestFunction check, ExceptionTest check_exception, auto&& input
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -910,7 +904,6 @@ void test_status(TestFunction check, ExceptionTest check_exception, auto&& input
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
diff --git a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h
index e6f8164c536421..8be3d9ab274a61 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h
+++ b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/format.functions.tests.h
@@ -34,7 +34,6 @@ void format_test_vector_bool(TestFunction check, ExceptionTest check_exception,
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
diff --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.tests.h b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.tests.h
index 2716f461895c8d..3ebaa054f0cabc 100644
--- a/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.tests.h
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/format.functions.tests.h
@@ -45,7 +45,6 @@ void test_char(TestFunction check, ExceptionTest check_exception) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -87,7 +86,6 @@ void test_char(TestFunction check, ExceptionTest check_exception) {
   check(SV("{__'a': 'A'___, __'b': 'B'___, __'c': 'C'___}"), SV("{::_^{}}"), input, 13);
   check(SV("{#####'a': 'A', #####'b': 'B', #####'c': 'C'}"), SV("{::#>{}}"), input, 13);
 
-  check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
   check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
@@ -157,7 +155,6 @@ void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -198,7 +195,6 @@ void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
   check(SV("{__'a': 'A'___, __'b': 'B'___, __'c': 'C'___}"), SV("{::_^{}}"), input, 13);
   check(SV("{#####'a': 'A', #####'b': 'B', #####'c': 'C'}"), SV("{::#>{}}"), input, 13);
 
-  check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
   check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
@@ -267,7 +263,6 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -308,7 +303,6 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
   check(SV("{_false: 0_, _true: 42_, _true: 1__}"), SV("{::_^{}}"), input, 10);
   check(SV("{##false: 0, ##true: 42, ###true: 1}"), SV("{::#>{}}"), input, 10);
 
-  check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
   check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
@@ -369,7 +363,6 @@ void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -410,7 +403,6 @@ void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
   check(SV("{_-42: 42__, __1: -1___, _42: -42__}"), SV("{::_^{}}"), input, 10);
   check(SV("{###-42: 42, #####1: -1, ###42: -42}"), SV("{::#>{}}"), input, 10);
 
-  check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
   check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
@@ -478,7 +470,6 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -519,7 +510,6 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception) {
   check(SV("{_-42: 42__, __1: -1___}"), SV("{::_^{}}"), input, 10);
   check(SV("{###-42: 42, #####1: -1}"), SV("{::#>{}}"), input, 10);
 
-  check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
   check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
@@ -582,7 +572,6 @@ void test_pointer(TestFunction check, ExceptionTest check_exception) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
@@ -621,7 +610,6 @@ void test_pointer(TestFunction check, ExceptionTest check_exception) {
   check(SV("{__0x0: 0x0___}"), SV("{::_^{}}"), input, 13);
   check(SV("{#####0x0: 0x0}"), SV("{::#>{}}"), input, 13);
 
-  check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
   check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
@@ -685,7 +673,6 @@ void test_string(TestFunction check, ExceptionTest check_exception) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:#}"), input);
@@ -724,7 +711,6 @@ void test_string(TestFunction check, ExceptionTest check_exception) {
   check(SV(R"({__"hello": "HELLO"___, __"world": "WORLD"___})"), SV("{::_^{}}"), input, 21);
   check(SV(R"({#####"hello": "HELLO", #####"world": "WORLD"})"), SV("{::#>{}}"), input, 21);
 
-  check_exception("The fill option contains an invalid value", SV("{:::<}"), input);
   check_exception("The format string contains an invalid escape sequence", SV("{::}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{::{<}"), input);
 
@@ -788,7 +774,6 @@ void test_status(TestFunction check, ExceptionTest check_exception) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
diff --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.tests.h b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.tests.h
index a4d8c2d34c333f..e300b7713e48ce 100644
--- a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.tests.h
+++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/format.functions.tests.h
@@ -52,7 +52,6 @@ void test_char_default(TestFunction check, ExceptionTest check_exception) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -156,7 +155,7 @@ void test_char_string(TestFunction check, [[maybe_unused]] ExceptionTest check_e
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<s}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<s}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<s}"), input);
+  check_exception("The type option contains an invalid value for a character formatting argument", SV("{::<s}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-s}"), input);
@@ -215,7 +214,7 @@ void test_char_escaped_string(TestFunction check, [[maybe_unused]] ExceptionTest
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<?s}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<?s}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<?s}"), input);
+  check_exception("The format specifier should consume the input or end with a '}'", SV("{::<?s}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-?s}"), input);
@@ -289,7 +288,6 @@ void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -405,7 +403,6 @@ void test_bool(TestFunction check, ExceptionTest check_exception) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -512,7 +509,6 @@ void test_bool_multiset(TestFunction check, ExceptionTest check_exception) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -621,7 +617,6 @@ void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
 
   check_exception("The format string contains an invalid escape sequence", SV("{:}<}"), input);
   check_exception("The fill option contains an invalid value", SV("{:{<}"), input);
-  check_exception("The fill option contains an invalid value", SV("{::<}"), input);
 
   // *** sign ***
   check_exception("The format specifier should consume the input or end with a '}'", SV("{:-}"), input);
@@ -730,7 +725,6 @@ void test_floating_point(TestFunction check, ExceptionTest check_exception, auto
 
   check_exception("The format string contains an invalid escape sequence", SV(...
[truncated]

@mordante mordante self-assigned this Feb 16, 2024
Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this. Since the patch is a draft I mainly glanced over it.

I'm curious, why did you add __has_range_underlying_spec_ instead of using __use_range_fill_?

@poyaoc97
Copy link
Member Author

poyaoc97 commented Feb 16, 2024

Because the tuple formatter like the range formatter prohibits ':' as a fill (_use_range_fill = true) but it doesn't have an underlying format-spec. So I feel the need for __has_range_underlying_spec.

For example, {::<} for tuples is a no-go but OK (align left, no fill for the underlying formatter) for ranges (__has_range_underlying_spec_ = true for this case).

@mordante
Copy link
Member

Because the tuple formatter like the range formatter prohibits ':' as a fill (_use_range_fill = true) but it doesn't have an underlying format-spec. So {::<} for tuples is a no-go but OK (align left, no fill for the underlying formatter) for ranges (__has_range_underlying_spec_ = true for this case).

I expected that motivation. I think it would be more future proof to handle tuple the same and get a slightly worse error message. If tuple gets an underlying format-spec we're less likely to reintroduce this bug. (I am investigating this feature for a future C++ proposal.)

@poyaoc97
Copy link
Member Author

I think it would be more future proof to handle tuple the same and get a slightly worse error message.

OK, will update the patch tmr. Looks like it would bump into std::__throw_format_error("The format specifier should consume the input or end with a '}'");, no big deal.

If tuple gets an underlying format-spec we're less likely to reintroduce this bug. (I am investigating this feature for a future C++ proposal.)

Do you have a timeline you would like to share? :)
Would be cool to see it on the C++26 train.

@mordante
Copy link
Member

If tuple gets an underlying format-spec we're less likely to reintroduce this bug. (I am investigating this feature for a future C++ proposal.)

Do you have a timeline you would like to share? :) Would be cool to see it on the C++26 train.

My time-line heavily depends on the available time I have ;-) Still I hope to get a paper done before the end of next month.

@poyaoc97 poyaoc97 marked this pull request as ready for review February 18, 2024 14:27
@poyaoc97 poyaoc97 requested a review from a team as a code owner February 18, 2024 14:27
@poyaoc97
Copy link
Member Author

Ping~

Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping~

Sorry I didn't have time to look at this earlier.

Mainly looks good one small nit.

Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more change and then I'm happy with the patch.

@poyaoc97 poyaoc97 merged commit b29301c into llvm:main Mar 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants